26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
135 for(
int x = 0; x < 4; x++)
144 for(
int x = 0; x < 4; x++)
153 for(
int x = 0; x < 4; x++)
158 for(
int x = 0; x < 4; x++)
162 for(
int x = 0; x < 3; x++)
199 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete FrontCodePtr");
262 for(
int x = 0; x < 4; x++)
266 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
271 for(
int x = 0; x < 4; x++)
275 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
304 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
370 bool TempDerail =
false;
416 else if((NextElementPosition > -1) && (NextEntryPos > -1))
487 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
497 for(
int x = 0; x < 4; x++)
504 for(
int x = 0; x < 4; x++)
765 int LockedVectorNumber;
890 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
891 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
892 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
893 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
894 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
895 "of a shortage of on train crew"};
902 if(DwellTime < TDateTime(30.0 / 86400))
904 DwellTime = TDateTime(30.0 / 86400);
906 int randval = random(10000);
911 if(randval < Utilities->MinorDelayCutoff)
918 if(randval < Utilities->ModerateDelayCutoff)
925 if(randval < Utilities->MajorDelayCutoff)
940 if(
NewDelay <
double(DwellTime) * 1440)
946 NewDelay -= double(DwellTime) * 1440;
1005 int randval2 = rand() % 24;
1006 AnsiString Reason = ReasonArray[randval2];
1009 " minutes because " + Reason);
1015 " minutes because of a minor problem");
1158 if(BufferLocation ==
"")
1163 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1225 int NextElementPosition, NextEntryPos;
1249 NextElementPosition = -1;
1252 if((NextElementPosition > -1) && (NextEntryPos > -1))
1370 AnsiString StationName;
1381 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1394 if((NextElementPosition > -1) && (NextEntryPos > -1))
1528 if(TIFEntryPos == 0)
1564 if(NextElementPosition > -1)
1601 AnsiString Loc =
"";
1602 bool LocNamed =
false;
1631 Loc =
"outside railway";
1663 NextElementPosition = -1;
1674 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1692 if((NextElementPosition > -1) && (NextEntryPos > -1))
1730 FirstPair.second).
GetELink() == TempELink))
1735 SecondPair.second).
GetELink() == TempELink))
1749 FirstPair.second).
GetELink() == TempELink))
1754 SecondPair.second).
GetELink() == TempELink))
1768 FirstPair.second).
GetELink() == TempELink))
1773 SecondPair.second).
GetELink() == TempELink))
1803 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1806 int NewLastElement = 0, NewLastExitPos = 0;
1824 if(NewLastElement == -1)
1827 throw Exception(
"Error, Connection = -1 in Continuation loop in UpdateTrain");
1830 if(NewLastExitPos == -1)
1832 throw Exception(
"Error, ConnLinkPos = -1 in Continuation loop in UpdateTrain");
1834 LastElement = NewLastElement;
1835 LastExitPos = NewLastExitPos;
1838 if(CumDistance < 1200)
1844 int FirstDistance = 0;
1845 if(CumDistance >= 1200)
1847 FirstDistance = 100;
1851 FirstDistance = 1200 - CumDistance;
1853 if(FirstDistance < 100)
1855 FirstDistance = 100;
1881 if(VectorIT->RouteNumber == RouteNumber)
1918 " failed when changing aspect.\nTrains can only pass under signaller control.");
1952 LockedVectorNumber)))
2111 for(
int x = 0; x < 4; x++)
2118 for(
int x = 0; x < 4; x++)
2144 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2149 if(OtherTrainEntryPos == -1)
2151 throw Exception(
"Error - OtherTrainEntryPos not set");
2170 int OtherTrainID = -1;
2171 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2262 bool StopRequired =
false;
2275 int NextElementEntryPos = -1;
2276 int NextElementExitPos = -1;
2277 bool TrainOnNextElement =
false;
2278 bool StopSignalAtNextElement =
false;
2279 if(ForwardConnection)
2287 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2289 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2345 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2558 if(Code.Length() != 4)
2562 for(
int x = 1; x < 5; x++)
2569 for(
int x = 0; x < 4; x++)
2732 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2745 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2760 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2769 TRect SourceRect, DestRect;
2771 DestRect.init(0, 0, 8, 8);
2774 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2776 TempGraphic->PixelFormat = pf8bit;
2777 TempGraphic->Width = 16;
2778 TempGraphic->Height = 16;
2784 TempGraphic->Transparent =
true;
2788 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2789 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2795 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2803 else if(TempElement.
SpeedTag == 89)
2807 else if(TempElement.
SpeedTag == 90)
2811 else if(TempElement.
SpeedTag == 91)
2815 else if(TempElement.
SpeedTag == 92)
2819 else if(TempElement.
SpeedTag == 93)
2823 else if(TempElement.
SpeedTag == 94)
2827 else if(TempElement.
SpeedTag == 95)
2831 TempGraphic->Transparent =
true;
2835 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2836 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2838 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2845 for(
int x = 0; x < 40; x++)
2860 TempGraphic->Transparent =
true;
2864 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2865 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2867 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2881 TempGraphic->Transparent =
true;
2885 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2886 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2890 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2893 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2898 TempGraphic->Transparent =
true;
2902 int BDVectorPos = -1;
2911 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2916 TempGraphic->Transparent =
true;
2920 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2921 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2923 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2929 TempGraphic->Transparent =
true;
2933 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2934 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2936 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3202 throw Exception(
"Error, same train on two different bridge tracks");
3248 AnsiString(EntryPos) +
"," +
HeadCode);
3265 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3284 AnsiString(EntryPos) +
"," +
HeadCode);
3293 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3326 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3327 int LockedVectorNumber;
3340 TRect SourceRect, DestRect;
3341 DestRect.init(0, 0, 8, 8);
3348 int FirstELink, SecondELink = -1;
3351 if(RoutePair2.first > -1)
3360 if(SecondELink == -1)
3362 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3367 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3377 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3378 DestGraphic->PixelFormat = pf8bit;
3379 DestGraphic->Width = 8;
3380 DestGraphic->Height = 8;
3381 DestGraphic->Transparent =
true;
3384 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3393 PrefDirElement, LockedVectorNumber))
3408 if(ElementEntryPos > 1)
3430 AnsiString(EntryPos) +
"," +
HeadCode);
3432 bool WrongRoute =
false;
3458 int LinkNumber = TrackElement.
Link[EntryPos];
3459 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3464 bool LogActionErrorCalled =
false;
3474 LogActionErrorCalled =
true;
3491 else if(LinkNumber == 3)
3499 LogActionErrorCalled =
true;
3516 else if(LinkNumber == 7)
3524 LogActionErrorCalled =
true;
3541 else if(LinkNumber == 9)
3549 LogActionErrorCalled =
true;
3581 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3586 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3596 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3601 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3610 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3631 bool ColourError =
false, ColourError2 =
false;
3636 ColourError2 =
true;
3638 for(
int x = 0; x < 4; x++)
3643 ColourError2 =
true;
3649 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3653 for(
int x = 0; x < 4; x++)
3740 AnsiString(EntryPos) +
"," +
HeadCode);
3741 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3742 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3743 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3744 TrainInFrontInSignallerModeFlag =
false;
3745 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3746 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3747 bool SignallerStopRequired =
false;
3758 if(CurrentTrackVectorPosition > -1)
3762 if((EntryPos == 0) || (EntryPos == 2))
3775 else if(EntryPos == 1)
3799 EntryHalfLength = CurrentElementHalfLength;
3804 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3808 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3855 FrontElementMaxSpeed = LimitingSpeed;
3890 double ExitSpeedAtMaxBraking;
3895 ExitSpeedAtMaxBraking = 0;
3905 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3907 SpeedToUse = ExitSpeedAtMaxBraking;
3911 SpeedToUse = LimitingSpeed;
3926 RedSignalFlag =
false;
3927 BuffersFlag =
false;
3928 StationFlag =
false;
3929 BuffersOrContinuationNowFlag =
false;
3930 ContinuationNextFlag =
false;
3933 CumulativeLength += (2 * CurrentElementHalfLength);
3936 SignallerStopRequired =
true;
3958 bool StopRequired =
false;
3972 StationFlag =
false;
3978 BuffersOrContinuationNowFlag =
true;
3980 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
3984 if((EntryPos == 0) || (EntryPos == 2))
4006 if(NextTrackVectorPosition > -1)
4011 if((NextEntryPos == 0) || (NextEntryPos == 2))
4024 else if(NextEntryPos == 1)
4037 if(NextEntryPos > 1)
4051 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4063 RedSignalFlag =
true;
4085 TrainInFrontInSignallerModeFlag =
true;
4109 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4121 double MaxHalfSpeed;
4125 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4127 MaxHalfSpeed = FrontElementMaxSpeed;
4131 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4139 bool HalfSpeedLimited =
false;
4143 HalfSpeedLimited =
true;
4173 if(HalfSpeedLimited)
4198 if(SignallerStopRequired)
4214 int TempMaxExitSpeed;
4217 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4219 MaxExitSpeedAtHalfBraking = 0;
4223 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4227 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4229 TempMaxExitSpeed = FrontElementMaxSpeed;
4233 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4245 if(ExitSpeedHalfSquared < 10)
4255 if(ExitSpeedFullSquared < 10)
4327 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4328 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4352 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4353 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4363 if(!BuffersOrContinuationNowFlag)
4365 if(NextSpeedLimit < LimitingSpeed)
4367 LimitingSpeed = NextSpeedLimit;
4371 int TempMaxExitSpeed;
4375 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4377 MaxExitSpeedAtHalfBraking = 0;
4381 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4383 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4385 TempMaxExitSpeed = FrontElementMaxSpeed;
4389 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4400 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4413 if(!BuffersOrContinuationNowFlag)
4415 CurrentTrackVectorPosition = NextTrackVectorPosition;
4416 EntryPos = NextEntryPos;
4417 CurrentElementHalfLength = NextElementHalfLength;
4420 ContinuationNextFlag =
true;
4424 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4444 if(ExitSpeedHalfSquared < 10)
4454 if(ExitSpeedFullSquared < 10)
4517 double DeltaExitTimeToMaxInSecs;
4518 double DistanceToMax;
4527 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4529 DistanceToMax = EntryHalfLength;
4532 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4533 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4550 double DeltaExitTimeToMaxInSecs;
4551 double DistanceToMax;
4560 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4562 DistanceToMax = EntryHalfLength / 2;
4565 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4566 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4577 if(ExitSpeedHalfSquared < 10)
4587 if(ExitSpeedFullSquared < 10)
4606 if((EntryPos == 0) || (EntryPos == 2))
4628 if(NextTrackVectorPosition > -1)
4630 int NextElementLength;
4631 if(NextEntryPos > 1)
4639 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4826 int ElementCount = 0;
4834 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4852 CurrentTrackVectorPosition).
Attribute != 4))
4892 if((EntryPos == 0) || (EntryPos == 2))
4914 CurrentTrackVectorPosition = NextTrackVectorPosition;
4915 EntryPos = NextEntryPos;
4917 if(ElementCount > 1000)
4945 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4970 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4971 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4972 int RouteStartPosition;
4974 int PlatformPosition;
4976 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
4992 if(Distance > (4000 + LeadElementDistance))
5015 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5018 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5064 if(!PlatformFoundFlag)
5066 PlatformPosition = CurrentTrackVectorPosition;
5069 PlatformFoundFlag =
true;
5085 if((EntryPos == 0) || (EntryPos == 2))
5129 if(ElementNumber < 2)
5131 SkipRouteCheck =
true;
5135 SkipRouteCheck =
false;
5137 if(ElementNumber == 1)
5139 RouteStartPosition = CurrentTrackVectorPosition;
5149 if(ElementNumber > 1)
5153 RouteOrPartRouteSet =
true;
5157 RouteOrPartRouteSet =
false;
5160 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5167 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5168 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5180 Distance += CurrentTrackElement.
Length01;
5184 Distance += CurrentTrackElement.
Length23;
5186 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5187 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5188 CurrentTrackVectorPosition = NextTrackVectorPosition;
5189 EntryPos = NextEntryPos;
5226 return(RepeatHeadCode);
5248 bool FrontValid =
false, RearValid =
false;
5249 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5253 TrainToBeJoinedBy = NULL;
5267 int TrainToBeJoinedByID = -1;
5288 if((TrainToBeJoinedByID < 0) && RearValid)
5307 if(TrainToBeJoinedByID < 0)
5309 TrainToBeJoinedBy = NULL;
5314 if(!TrainToBeJoinedBy->
Stopped())
5316 TrainToBeJoinedBy = NULL;
5327 TDateTime TimetableNonRepeatTime,
bool Warning)
5362 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5363 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5364 int IntMinsLate = 0;
5369 ActionLog =
" arrived at ";
5378 ActionLog =
" terminated at ";
5383 ActionLog =
" departed from ";
5385 if(ActionType ==
Pass)
5387 ActionLog =
" passed ";
5391 ActionLog =
" created at ";
5393 if(ActionType ==
Enter)
5395 ActionLog =
" entered railway at ";
5397 if(ActionType ==
Leave)
5399 ActionLog =
" left railway at ";
5403 ActionLog =
" split from front to ";
5407 ActionLog =
" split from rear to ";
5411 ActionLog =
" joined by ";
5415 ActionLog =
" changed direction at ";
5419 ActionLog =
" became new service ";
5423 ActionLog =
" taken under signaller control at ";
5427 ActionLog =
" restored to timetable control at ";
5433 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5437 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5441 ActionLog =
" REMOVED FROM RAILWAY at ";
5446 ActionLog =
" received signaller authority to proceed";
5450 ActionLog =
" received signaller authority to step forward";
5454 ActionLog =
" changed direction under signaller control at ";
5458 ActionLog =
" received signaller authority to pass stop signal";
5462 ActionLog =
" received signaller instruction to stop";
5466 ActionLog =
" stopped on signaller instruction ";
5470 ActionLog =
" joined under signaller control by ";
5474 ActionLog =
" suffered an onboard power failure at ";
5478 ActionLog =
" failure repaired at ";
5482 ActionLog =
" left railway under signaller control at ";
5484 if(OtherHeadCode !=
"")
5486 OtherHeadCode +=
" at ";
5499 bool TimePerformance =
true;
5507 TimePerformance =
false;
5511 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5513 if(ActionType ==
Pass)
5527 IntMinsLate = int(ceil(MinsLate));
5531 IntMinsLate = int(floor(MinsLate));
5533 if(IntMinsLate == 0)
5535 PerfLog =
" on time";
5537 else if(IntMinsLate == 1)
5539 PerfLog =
" 1 minute late";
5541 else if(IntMinsLate == -1)
5543 PerfLog =
" 1 minute early";
5545 else if(IntMinsLate > 1)
5547 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5549 else if(IntMinsLate < -1)
5551 int PosIntMinsLate = -IntMinsLate;
5552 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5554 if(LocationName.Pos(
'-') > 0)
5556 PerfLog =
"," + PerfLog;
5570 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5574 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5579 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5585 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5589 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5594 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5600 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5604 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5609 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5615 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5619 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5638 AnsiString LocName =
"";
5705 if(LocationName ==
"")
5709 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5710 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5711 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5715 if(LocationName !=
"")
5723 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5728 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5742 int LeadPosA = FirstNamedElementPos;
5743 int LeadPosB = FirstNamedLinkedElementPos;
5744 int LeadPosC = SecondNamedElementPos;
5745 int LeadPosD = SecondNamedLinkedElementPos;
5747 int LeadNumAtLoc = 0;
5764 if(LeadNumAtLoc < 4)
5768 SecondNamedLinkedElementPos))
5770 FirstNamedElementPos = LeadPosA;
5771 FirstNamedLinkedElementPos = LeadPosB;
5772 SecondNamedElementPos = LeadPosC;
5773 SecondNamedLinkedElementPos = LeadPosD;
5777 int MidNumAtLoc = 0;
5794 if(LeadNumAtLoc > MidNumAtLoc)
5797 FirstNamedElementPos = LeadPosA;
5798 FirstNamedLinkedElementPos = LeadPosB;
5799 SecondNamedElementPos = LeadPosC;
5800 SecondNamedLinkedElementPos = LeadPosD;
5814 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5824 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5825 FrontTrainRearPosition = FirstNamedElementPos;
5826 RearTrainFrontPosition = SecondNamedElementPos;
5827 RearTrainRearPosition = SecondNamedLinkedElementPos;
5831 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5832 FrontTrainRearPosition = SecondNamedElementPos;
5833 RearTrainFrontPosition = FirstNamedElementPos;
5834 RearTrainRearPosition = FirstNamedLinkedElementPos;
5841 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5842 FrontTrainRearPosition = SecondNamedElementPos;
5843 RearTrainFrontPosition = FirstNamedElementPos;
5844 RearTrainRearPosition = FirstNamedLinkedElementPos;
5848 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5849 FrontTrainRearPosition = FirstNamedElementPos;
5850 RearTrainFrontPosition = SecondNamedElementPos;
5851 RearTrainRearPosition = SecondNamedLinkedElementPos;
5854 RearTrainExitPos = -1;
5855 for(
int x = 0; x < 4; x++)
5859 RearTrainExitPos = x;
5863 if(RearTrainExitPos == -1)
5865 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5867 FrontTrainExitPos = -1;
5868 for(
int x = 0; x < 4; x++)
5872 FrontTrainExitPos = x;
5876 if(FrontTrainExitPos == -1)
5878 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5881 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5888 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5908 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5916 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5917 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5918 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6015 if(LocationName ==
"")
6019 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
6020 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
6021 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
6025 if(LocationName !=
"")
6032 SecondNamedLinkedElementPos))
6036 SecondNamedLinkedElementPos))
6050 int LeadPosA = FirstNamedElementPos;
6051 int LeadPosB = FirstNamedLinkedElementPos;
6052 int LeadPosC = SecondNamedElementPos;
6053 int LeadPosD = SecondNamedLinkedElementPos;
6055 int LeadNumAtLoc = 0;
6072 if(LeadNumAtLoc < 4)
6076 SecondNamedLinkedElementPos))
6078 FirstNamedElementPos = LeadPosA;
6079 FirstNamedLinkedElementPos = LeadPosB;
6080 SecondNamedElementPos = LeadPosC;
6081 SecondNamedLinkedElementPos = LeadPosD;
6085 int MidNumAtLoc = 0;
6102 if(LeadNumAtLoc > MidNumAtLoc)
6105 FirstNamedElementPos = LeadPosA;
6106 FirstNamedLinkedElementPos = LeadPosB;
6107 SecondNamedElementPos = LeadPosC;
6108 SecondNamedLinkedElementPos = LeadPosD;
6122 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6132 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6133 FrontTrainRearPosition = FirstNamedElementPos;
6134 RearTrainFrontPosition = SecondNamedElementPos;
6135 RearTrainRearPosition = SecondNamedLinkedElementPos;
6139 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6140 FrontTrainRearPosition = SecondNamedElementPos;
6141 RearTrainFrontPosition = FirstNamedElementPos;
6142 RearTrainRearPosition = FirstNamedLinkedElementPos;
6149 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6150 FrontTrainRearPosition = SecondNamedElementPos;
6151 RearTrainFrontPosition = FirstNamedElementPos;
6152 RearTrainRearPosition = FirstNamedLinkedElementPos;
6156 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6157 FrontTrainRearPosition = FirstNamedElementPos;
6158 RearTrainFrontPosition = SecondNamedElementPos;
6159 RearTrainRearPosition = SecondNamedLinkedElementPos;
6162 RearTrainExitPos = -1;
6163 for(
int x = 0; x < 4; x++)
6167 RearTrainExitPos = x;
6171 if(RearTrainExitPos == -1)
6173 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6175 FrontTrainExitPos = -1;
6176 for(
int x = 0; x < 4; x++)
6180 FrontTrainExitPos = x;
6184 if(FrontTrainExitPos == -1)
6186 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6189 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6196 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6216 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6224 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6225 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6226 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6365 TTrain *TrainToBeJoinedBy;
6398 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6400 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6460 int RouteNumber = -1;
6465 int CorrectRouteID = OR.
RouteID;
6470 bool FirstPass =
true;
6475 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6582 for(
int x = 0; x < IncNum; x++)
6615 else if(Ptr->
Command ==
"jbo")
6626 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6632 bool IncludeFER =
false;
6640 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6645 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6656 else if(Ptr->
Command ==
"Fjo")
6662 else if(Ptr->
Command ==
"Frh")
6672 else if(Ptr->
Command ==
"Frh-sh")
6723 else if(Ptr->
Command ==
"jbo")
6728 else if(Ptr->
Command ==
"cdt")
6736 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7123 int RouteNumber = -1;
7128 int CorrectRouteID = OR.
RouteID;
7133 bool FirstPass =
true;
7138 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7166 ",FloatingLabelNextString" +
"," +
HeadCode);
7167 AnsiString RetStr =
"", LocationName =
"";
7173 throw Exception(
"Error - start entry in FloatingLabelNextString");
7217 else if(Ptr->
Command ==
"Fns")
7223 else if(Ptr->
Command ==
"F-nshs")
7254 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7256 else if(Ptr->
Command ==
"Frh")
7258 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7260 else if(Ptr->
Command ==
"Fer")
7262 AnsiString AllowedExits =
"";
7265 else if(Ptr->
Command ==
"Fjo")
7270 else if(Ptr->
Command ==
"jbo")
7275 else if(Ptr->
Command ==
"fsp")
7280 else if(Ptr->
Command ==
"rsp")
7285 else if(Ptr->
Command ==
"cdt")
7294 throw Exception(
"Error - start entry in FloatingLabelNextString");
7338 else if(Ptr->
Command ==
"Fns")
7344 else if(Ptr->
Command ==
"F-nshs")
7375 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7377 else if(Ptr->
Command ==
"Frh")
7379 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7381 else if(Ptr->
Command ==
"Fer")
7383 AnsiString AllowedExits =
"";
7386 else if(Ptr->
Command ==
"Fjo")
7391 else if(Ptr->
Command ==
"jbo")
7396 else if(Ptr->
Command ==
"fsp")
7401 else if(Ptr->
Command ==
"rsp")
7406 else if(Ptr->
Command ==
"cdt")
7550 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7551 AnsiString DepTime =
"", EventTime =
"";
7552 bool CDTFlag =
false;
7554 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7555 AnsiString TowardsLocation =
"";
7558 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7560 TowardsLocation = AVI->LocationName;
7562 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7571 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7577 if(AVI->Command ==
"cdt")
7582 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7585 RetStr +=
"\nNew service splits at " + EventTime;
7589 if(AVI->Command ==
"jbo")
7592 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
7596 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7601 if(TowardsLocation !=
"")
7603 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7607 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7612 if(TowardsLocation !=
"")
7614 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7618 RetStr +=
"\nNew service departs at " + DepTime;
7636 ",FloatingTimetableString" +
"," +
HeadCode);
7637 AnsiString RetStr =
"", PartStr =
"";
7639 bool SkipDep =
false, SkipDepActedOn =
false;
7645 throw Exception(
"Error - start entry in FloatingTimetableString");
7648 bool FirstPass =
true;
7661 AnsiString TrainLoc =
"";
7707 AnsiString TrainLoc =
"";
7747 else if(Ptr->
Command ==
"Fns")
7753 else if(Ptr->
Command ==
"F-nshs")
7786 else if(Ptr->
Command ==
"Frh")
7790 else if(Ptr->
Command ==
"Fer")
7792 AnsiString AllowedExits =
"";
7795 else if(Ptr->
Command ==
"Fjo")
7800 else if(Ptr->
Command ==
"jbo")
7805 else if(Ptr->
Command ==
"fsp")
7810 else if(Ptr->
Command ==
"rsp")
7815 else if(Ptr->
Command ==
"cdt")
7821 RetStr = RetStr +
'\n' + PartStr;
7835 SkipDepActedOn =
true;
7846 RetStr =
"Timetable finished";
7850 RetStr =
"No timetable";
7854 return(
"Timetable:\n" + RetStr);
8007 bool ForwardHeadCode;
8011 ForwardHeadCode =
true;
8016 ForwardHeadCode =
false;
8159 if(ColourNumber == 0)
8163 else if(ColourNumber == 1)
8167 else if(ColourNumber == 2)
8171 else if(ColourNumber == 3)
8175 else if(ColourNumber == 4)
8179 else if(ColourNumber == 5)
8183 else if(ColourNumber == 6)
8187 else if(ColourNumber == 7)
8191 else if(ColourNumber == 8)
8195 else if(ColourNumber == 9)
8199 else if(ColourNumber == 10)
8203 else if(ColourNumber == 11)
8207 else if(ColourNumber == 12)
8211 else if(ColourNumber == 13)
8215 else if(ColourNumber == 14)
8227 for(
int x = 0; x < 4; x++)
8234 for(
int x = 0; x < 4; x++)
8319 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8322 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8323 bool GiveMessagesFalse =
false;
8324 bool CheckLocationsExistInRailwayTrue =
true;
8331 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8334 if(Marker[6] ==
'1')
8799 bool HideFlashingTrain =
true;
8802 Graphics::TBitmap *SmallTrainBitmap;
8843 HideFlashingTrain =
false;
8848 HideFlashingTrain =
false;
8853 HideFlashingTrain =
false;
8858 HideFlashingTrain =
false;
8863 HideFlashingTrain =
false;
8867 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
8871 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
8895 for(
int y = 0; y < 3; y++)
8899 bool FoundFlag =
false;
8910 if(IMPair.first != IMPair.second)
8937 if((LocationName ==
"") && (
MidElement > -1))
8941 if((LocationName ==
"") && (
LagElement > -1))
8945 if(LocationName ==
"")
8947 throw Exception(
"Error - Location name not set in TrainAtLocation");
8958 for(
int x = 0; x < 4; x++)
8970 for(
int x = 0; x < 4; x++)
8987 AnsiString(LinkNumber) +
"," +
HeadCode);
9039 int DistanceToRedSignal = 0, DistanceToExit = -1;
9040 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9044 float MinsEarly = 0;
9045 TDateTime DepartureTime;
9046 TDateTime ArrivalTime;
9074 if(TempTTE < LastTimeToExit)
9109 if(TempTTE < LastTimeToExit)
9132 if(TempTTE < LastTimeToExit)
9162 if(TempTTE < LastTimeToExit)
9185 if(TempTTE < LastTimeToExit)
9228 float CurrentStopTime;
9229 float LaterStopTime;
9230 float RecoverableTime;
9238 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9245 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9246 bool DistanceToExitSet = (DistanceToExit > -1);
9247 int GenericDistance = DistanceToRedSignal;
9248 if(DistanceToExitSet)
9250 GenericDistance = DistanceToExit;
9266 float TimeToSubtract, TotalStopTime;
9269 TimeToSubtract = RecoverableTime;
9312 if(CurrentStopTime > 0)
9314 TotalStopTime = CurrentStopTime + LaterStopTime;
9323 else if((MinsEarly > 0) && !
Stopped())
9325 TotalStopTime = LaterStopTime + MinsEarly;
9329 if(LaterStopTime == 0)
9331 TotalStopTime = CurrentStopTime;
9337 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9340 if(AvTrackSpeed < 30)
9344 int Speed = AvTrackSpeed;
9354 if(DistanceToRedSignalSet)
9356 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9366 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9389 if((NextEntryPos == 0) || (NextEntryPos == 2))
9516 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9558 int IncrementalMinutes = 0;
9559 int IncrementalDigits = 0;
9567 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
9602 if(AVEntry0.
Command ==
"Snt-sh")
9607 int IncrementalMinutes = 0;
9608 int IncrementalDigits = 0;
9616 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
9659 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9739 AnsiString Loc =
"";
9740 bool ElementFound =
false;
9745 ElementFound =
true;
9750 ElementFound =
true;
9755 ElementFound =
true;
9784 else if(AVEntryPtr->
Command ==
"Fer")
9786 bool CorrectExit =
false;
9898 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9916 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9931 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
9942 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
9943 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
9944 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
9946 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
9947 "," + AnsiString(Mass) +
"," + ModeStr);
9949 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
9951 int RearExitPos = -1;
9953 for(
int x = 0; x < 4; x++)
9960 if(RearExitPos == -1)
9962 throw Exception(
"Error, RearExit == -1 in AddTrain");
9964 bool ReportFlag =
true;
9981 if(ModeStr ==
"Timetable")
9987 if(MaxRunningSpeed < 10)
9989 MaxRunningSpeed = 10;
9991 if(SignallerSpeed < 10)
9993 SignallerSpeed = 10;
9995 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
9996 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10003 if(SignallerControl)
10033 if(!SignallerControl)
10048 if(!SignallerControl)
10059 AnsiString Loc =
"";
10076 if(!SignallerControl)
10095 int RouteNumber = -1;
10096 bool SignalsSet =
false;
10103 int RouteStartPosition;
10107 if(FirstPair.first == RouteNumber)
10109 RouteStartPosition = FirstPair.second;
10111 else if(SecondPair.first == RouteNumber)
10113 RouteStartPosition = SecondPair.second;
10117 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10123 else if(RouteNumber > -1)
10143 int LinkedRouteNumber = -1;
10164 int RouteStartPosition;
10168 if(FirstPair.first == RouteNumber)
10170 RouteStartPosition = FirstPair.second;
10172 else if(SecondPair.first == RouteNumber)
10174 RouteStartPosition = SecondPair.second;
10178 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10184 else if(RouteNumber > -1)
10204 int LinkedRouteNumber = -1;
10225 AnsiString(TrackVectorNumber));
10228 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10237 throw Exception(
"Error, VecPos not set in EntryPos");
10239 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10244 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10249 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10263 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10271 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10281 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10302 return(RepeatTime);
10311 AnsiString RetStr =
"", PartStr =
"";
10319 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10327 if(Ptr->SignallerControl)
10329 RetStr =
"Train under signaller control";
10334 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10345 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10349 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10353 else if(Ptr->FormatType ==
PassTime)
10357 else if(Ptr->Command ==
"Fns")
10363 else if(Ptr->Command ==
"F-nshs")
10366 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10373 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10380 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10383 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10386 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10393 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10395 PartStr =
"Terminate at " + Ptr->LocationName;
10397 else if(Ptr->Command ==
"Frh")
10399 PartStr =
"Terminate at " + Ptr->LocationName;
10401 else if(Ptr->Command ==
"Fer")
10403 AnsiString AllowedExits;
10407 else if(Ptr->Command ==
"Fjo")
10410 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10412 else if(Ptr->Command ==
"jbo")
10415 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10417 else if(Ptr->Command ==
"fsp")
10422 else if(Ptr->Command ==
"rsp")
10427 else if(Ptr->Command ==
"cdt")
10433 RetStr = RetStr +
'\n' + PartStr;
10441 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10454 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10455 AnsiString DepTime =
"", EventTime =
"";
10456 bool CDTFlag =
false;
10458 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10459 AnsiString TowardsLocation =
"";
10462 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10464 TowardsLocation = AVI->LocationName;
10466 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10475 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10481 if(AVI->Command ==
"cdt")
10483 CDTFlag = !CDTFlag;
10486 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10489 RetStr +=
"\nNew service splits at " + EventTime;
10493 if(AVI->Command ==
"jbo")
10496 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10500 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10505 if(TowardsLocation !=
"")
10507 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10511 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10516 if(TowardsLocation !=
"")
10518 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
10522 RetStr +=
"\nNew service departs at " + DepTime;
10683 ActiveTrackElementNameMapEntry.second = 0;
10689 std::ifstream TTBLFile(FileName, std::ios_base::binary);
10692 if(TTBLFile.is_open())
10694 char *TrainTimetableString =
new char[10000];
10696 bool EndOfFile =
false;
10699 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10701 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10708 delete[] TrainTimetableString;
10712 AnsiString OneLine(TrainTimetableString);
10713 bool FinalCallFalse =
false;
10714 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10718 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10719 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10724 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
10726 delete[] TrainTimetableString;
10730 OneLine = AnsiString(TrainTimetableString);
10736 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
10738 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
10748 OneLine = AnsiString(TrainTimetableString);
10750 if(OneLine.Length() > 9999)
10752 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
10754 delete[] TrainTimetableString;
10758 bool FinalCallFalse =
false;
10759 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
10763 delete[] TrainTimetableString;
10767 if(EndOfFile && (Count < 2))
10770 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
10772 delete[] TrainTimetableString;
10778 delete[] TrainTimetableString;
10783 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
10794 bool CheckLocationsExistInRailway)
10919 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
10929 if(OneLine[1] !=
'*')
10931 int SCPos = OneLine.Pos(
';');
10942 bool AllCommas =
true;
10944 for(
int x = 1; x < OneLine.Length() + 1; x++)
10946 if(OneLine[x] !=
',')
10951 if(AllCommas || (OneLine ==
""))
10966 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
10967 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
10968 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
10969 TDateTime StartTime(0);
10971 bool Warning =
false;
10998 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
10999 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11000 double MaxBrakeRate = 0;
11001 double PowerAtRail = 0;
11002 int SignallerSpeed = 0;
11003 if(OneLine[1] ==
'*')
11009 int Pos = OneLine.Pos(
',');
11012 int SubStringLength = 20;
11013 if(OneLine.Length() < 20)
11015 SubStringLength = OneLine.Length();
11017 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11021 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11022 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11032 TempTrainDataEntry.
HeadCode = HeadCode;
11036 TempTrainDataEntry.
Mass = Mass;
11044 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11047 while(NewRemainder[NewRemainder.Length()] ==
',')
11049 if(NewRemainder.Length() > 1)
11051 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11060 if(NewRemainder ==
"")
11062 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11067 int CommaCount = 0;
11068 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11070 if(NewRemainder[x] ==
',')
11075 if(CommaCount == 0)
11077 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11079 int SubStringLength = 20;
11080 if(OneLine.Length() < 20)
11082 SubStringLength = OneLine.Length();
11085 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11086 OneLine.SubString(1, SubStringLength) +
"'....");
11091 AnsiString OneEntry =
"";
11096 bool FinishFlag =
false;
11097 for(
int x = 0; x < CommaCount + 1; x++)
11099 if((CommaCount == 0) || (x < CommaCount))
11104 if(CommaCount == 0)
11106 OneEntry = NewRemainder;
11111 Pos = NewRemainder.Pos(
',');
11112 OneEntry = NewRemainder.SubString(1, Pos - 1);
11113 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11119 RearStartOrRepeatMins = 0;
11120 FrontStartOrRepeatDigits = 0;
11121 NumberOfRepeats = 0;
11122 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11123 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11125 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11130 if(Warning && (Second ==
"Frh"))
11132 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11136 if(Warning && (Second ==
"Fjo"))
11139 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11145 if(SequenceType !=
Start)
11147 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11151 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11153 if(NewRemainder[1] !=
'R')
11156 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11162 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11166 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11169 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11175 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11180 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11185 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11188 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11195 if(SequenceType ==
Finish)
11204 TDateTime TempTime;
11210 ActionVectorEntry.
Warning = Warning;
11226 ActionVectorEntry.
Command = Second;
11241 else if(FormatType ==
TimeCmd)
11247 ActionVectorEntry.
Command = Second;
11255 ActionVectorEntry.
Command = Second;
11256 ActionVectorEntry.
ExitList = ExitList;
11264 ActionVectorEntry.
Command = Second;
11278 ActionVectorEntry.
Command = Second;
11289 ActionVectorEntry.
Command = Second;
11299 ActionVectorEntry.
Command = Second;
11308 ActionVectorEntry.
Command = Second;
11317 ActionVectorEntry.
Command = Second;
11323 ActionVectorEntry.
Command = Second;
11325 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11330 OneEntry = NewRemainder;
11335 RearStartOrRepeatMins = 0;
11336 FrontStartOrRepeatDigits = 0;
11337 NumberOfRepeats = 0;
11338 if((FinishFlag) && (OneEntry[1] !=
'R'))
11341 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11345 if(OneEntry[1] !=
'R')
11347 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11348 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11350 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11354 if(SequenceType !=
Finish)
11356 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11363 TDateTime TempTime;
11369 ActionVectorEntry.
Warning = Warning;
11376 ActionVectorEntry.
Command = Second;
11384 ActionVectorEntry.
Command = Second;
11393 ActionVectorEntry.
Command = Second;
11402 ActionVectorEntry.
Command = Second;
11412 ActionVectorEntry.
Command = Second;
11413 ActionVectorEntry.
ExitList = ExitList;
11417 ActionVectorEntry.
Command = Second;
11419 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11424 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11440 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11459 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
11464 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
11479 if(TimeStr.Length() < 5)
11484 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
11489 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
11494 if(TimeStr[3] !=
':')
11499 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
11504 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
11509 while(TimeStr.Length() > 5)
11511 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
11513 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
11514 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
11516 if((WholeHours + FracHour) >= 95.98334)
11521 Time = TDateTime((WholeHours + FracHour) / 24);
11528 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
11529 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
11538 TDateTime TempTime;
11540 if(OneEntry.Length() > 0)
11542 if(OneEntry[1] ==
'W')
11545 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
11549 if(OneEntry ==
"Frh")
11559 if(OneEntry.Length() < 7)
11564 int Pos = OneEntry.Pos(
';');
11572 First = OneEntry.SubString(1, 5);
11578 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
11580 if((Remainder[1] >=
'0') && (Remainder[1] <=
'9'))
11583 if(Remainder.Length() < 7)
11588 Pos = Remainder.Pos(
';');
11595 Second = Remainder.SubString(1, 5);
11601 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11614 Pos = Remainder.Pos(
';');
11617 Second = Remainder;
11618 if(Second ==
"cdt")
11643 if((Pos != 4) && (Pos != 7) && (Pos != 8))
11649 Second = Remainder.SubString(1, Pos - 1);
11651 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11653 Pos = Remainder.Pos(
';');
11660 Third = Remainder.SubString(1, Pos - 1);
11661 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
11663 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11666 int SpacePos = Third.Pos(
' ');
11672 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
11673 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
11675 if(CheckLocationsExistInRailway)
11685 if(Second ==
"Snt")
11688 SequenceType =
Start;
11697 SequenceType =
Start;
11708 if(Second ==
"Sns-sh")
11712 SequenceType =
Start;
11727 if(Second ==
"F-nshs")
11741 if(Second ==
"Sns-fsh")
11745 SequenceType =
Start;
11755 if(Second ==
"Fns-sh")
11775 if(Second ==
"pas")
11790 if(Second ==
"Fer")
11797 if(CheckLocationsExistInRailway)
11809 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
11810 (Second !=
"Frh-sh"))
11822 if(Second ==
"Frh-sh")
11830 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
11834 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
11838 if((Second ==
"Sfs") || (Second ==
"Sns"))
11840 SequenceType =
Start;
11858 if((LocStr[1] >=
'0') && (LocStr[1] <=
'9'))
11863 for(
int x = 1; x < LocStr.Length() + 1; x++)
11865 if(LocStr[x] <
' ')
11870 if(LocStr[x] >
'z')
11877 if(CheckLocationsExistInRailway)
11882 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
11883 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
11884 "that includes a continuation will not be valid.");
11902 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
11905 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
11910 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
11912 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
11914 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
11920 for(
int x = 3; x >= 0; x--)
11922 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
11923 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
11925 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
11941 AnsiString CurrentID =
"";
11943 if(IDSet.Length() == 0)
11945 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
11949 for(
int x = 1; x <= IDSet.Length(); x++)
11952 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
11954 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
11976 int Pos = IDSet.Pos(
' ');
11987 CurrentID = IDSet.SubString(1, Pos - 1);
11988 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12000 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12007 if(!ExitList.empty())
12009 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12011 if(*ELIT == VecPos)
12013 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12020 ExitList.push_back(VecPos);
12030 Pos = IDSet.Pos(
' ');
12037 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12044 AnsiString Remainder =
"";
12045 int SemiColonCount = 0;
12047 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12049 if(TrainInfoStr[x] ==
';')
12054 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12056 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12057 "'. Should be headcode + optional description for a continuing service;" +
12058 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12062 if(SemiColonCount == 0)
12064 HeadCode = TrainInfoStr;
12073 if(SemiColonCount == 1)
12075 Pos = TrainInfoStr.Pos(
';');
12076 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12077 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12083 if(Description ==
"")
12085 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12089 if(Description.Length() > 60)
12091 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12095 for(
int x = 1; x < Description.Length() + 1; x++)
12097 if((Description[x] <
' ') || (Description[x] >
'~'))
12099 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12108 Pos = TrainInfoStr.Pos(
';');
12109 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12110 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12116 Pos = Remainder.Pos(
';');
12117 Description = Remainder.SubString(1, Pos - 1);
12118 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12119 if(Description ==
"")
12121 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12125 if(Description.Length() > 60)
12127 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12131 for(
int x = 1; x < Description.Length() + 1; x++)
12133 if((Description[x] <
' ') || (Description[x] > 126))
12135 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12140 Pos = Remainder.Pos(
';');
12141 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12143 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12144 if(StartSpeedStr ==
"")
12146 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12150 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12152 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12154 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12159 StartSpeed = StartSpeedStr.ToInt();
12165 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12169 Pos = Remainder.Pos(
';');
12170 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12172 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12173 if(MaxRunningSpeedStr ==
"")
12175 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12179 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12181 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12183 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12188 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12194 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12198 if(MaxRunningSpeed < 10)
12201 MaxRunningSpeed = 10;
12204 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12208 Pos = Remainder.Pos(
';');
12209 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12211 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12214 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12218 for(
int x = 1; x < MassStr.Length() + 1; x++)
12220 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12222 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12227 Mass = MassStr.ToInt() * 1000;
12233 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12239 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12243 Pos = Remainder.Pos(
';');
12244 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12246 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12247 if(MaxBrakeForceStr ==
"")
12249 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12253 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12255 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12257 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12262 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12265 if((MaxBrakeForce / Mass) > 1)
12267 MaxBrakeForce = Mass;
12270 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12274 if((MaxBrakeForce / Mass) < 0.01)
12276 MaxBrakeForce = Mass * 0.01;
12279 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12284 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12286 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12288 if(SemiColonCount == 6)
12290 GrossPowerStr = Remainder;
12291 SignallerSpeedStr =
"30";
12295 Pos = Remainder.Pos(
';');
12296 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12297 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12300 if(GrossPowerStr ==
"")
12302 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12306 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12308 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12310 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12316 double GrossPower = GrossPowerStr.ToInt() * 1000;
12323 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12327 else if(GrossPower == 0)
12332 else if((GrossPower > 0) && (GrossPower < 10000))
12335 GrossPower = 10000;
12337 PowerAtRail = GrossPower * 0.8;
12341 if(SignallerSpeedStr ==
"")
12343 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12347 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12349 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12351 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12356 SignallerSpeed = SignallerSpeedStr.ToInt();
12362 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12366 if(SignallerSpeed < 10)
12369 SignallerSpeed = 10;
12372 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12390 if(OneEntry.Length() < 7)
12392 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12396 int SemiColonCount = 0;
12398 for(
int x = 1; x < OneEntry.Length() + 1; x++)
12400 if(OneEntry[x] ==
';')
12405 if(SemiColonCount != 3)
12407 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12411 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
12413 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
12417 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
12422 Pos = Remainder.Pos(
';');
12423 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
12425 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12426 if(MinutesStr ==
"")
12428 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
12432 if(MinutesStr.Length() > 3)
12435 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
12439 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
12441 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
12443 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
12448 RearStartOrRepeatMins = MinutesStr.ToInt();
12449 if(RearStartOrRepeatMins == 0)
12451 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
12455 Pos = Remainder.Pos(
';');
12456 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
12458 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12459 if(DigitsStr ==
"")
12461 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
12465 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
12467 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
12469 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
12474 if(DigitsStr.Length() > 2)
12476 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
12480 FrontStartOrRepeatDigits = DigitsStr.ToInt();
12494 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
12498 AnsiString NumberStr = Remainder;
12500 if(NumberStr ==
"")
12502 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
12506 if(NumberStr.Length() > 4)
12509 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
12513 for(
int x = 1; x < NumberStr.Length() + 1; x++)
12515 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
12518 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
12523 NumberOfRepeats = NumberStr.ToInt();
12524 if(NumberOfRepeats == 0)
12526 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
12698 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
12717 TwoLocationFlag =
false;
12723 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
12737 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
12753 "Error in timetable - a signaller control service can have no more than one item (a repeat) after the start event, see: " +
12765 "Error in timetable - a signaller control service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
12792 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
12803 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12808 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
12818 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12823 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
12833 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12844 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
12854 SecondPassMessage(GiveMessages,
"Error in timetable - the last event before the repeat must be a finish for: " + TDEntry.
HeadCode);
12866 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12873 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
12882 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " +
12902 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
12904 AnsiString LocationName =
"";
12920 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
12921 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12930 SecondPassMessage(GiveMessages,
"Error in timetable - 'Snt' or 'Snt-sh' event at stop location but start speed not zero for: " +
12939 if(AVEntry0.
Command ==
"Snt-sh")
12953 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
12969 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' followed by an illegal event for: " +
12970 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
12981 bool FoundFlag =
false;
12987 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
12999 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sfs', 'Sns', 'Sns-sh'or 'Sns-fsh' event for: " +
13012 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13021 ": an event should have had a location name associated with it but it could not be found");
13027 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13049 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13059 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish entry for: " + TDEntry.
HeadCode);
13066 if(AVEntry.
Command ==
"F-nshs")
13071 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
13099 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
13100 ". The event isn't valid for a stationary train.");
13110 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
13118 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
13119 ". The event isn't valid for a stationary train.");
13137 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
13138 ". The event isn't valid for a stationary train.");
13148 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
13156 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
13157 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
13175 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
13176 ". The event isn't valid for a moving train.");
13198 bool LastEntryIsAnArrival =
false;
13205 LastEntryIsAnArrival =
false;
13206 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13213 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13215 if(LastEntryIsAnArrival)
13219 LastEntryIsAnArrival =
false;
13225 LastEntryIsAnArrival =
true;
13232 LastEntryIsAnArrival =
true;
13233 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13240 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
13242 if(LastEntryIsAnArrival)
13246 LastEntryIsAnArrival =
false;
13252 LastEntryIsAnArrival =
true;
13262 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13270 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
13278 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
13279 ". The event isn't valid for a stationary train.");
13290 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
13298 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
13299 ". The event isn't valid for a moving train.");
13313 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13320 throw Exception(
"Timetable error, TimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13324 throw Exception(
"Timetable error, TimeLoc entry has neither arrival nor departure time set for " + TDEntry.
HeadCode);
13331 throw Exception(
"Timetable error, TimeTimeLoc entry has EventTime not -1 for " + TDEntry.
HeadCode);
13335 throw Exception(
"Timetable error, TimeTimeLoc entry has either arrival or departure time not set for " + TDEntry.
HeadCode);
13344 throw Exception(
"Timetable error, Cmd or PassTime entry has EventTime not set for " + TDEntry.
HeadCode);
13348 throw Exception(
"Timetable error, Cmd or PassTime entry has either arrival or departure time set for " + TDEntry.
HeadCode);
13355 throw Exception(
"Timetable error, Repeat entry has a time set for " + TDEntry.
HeadCode);
13366 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13381 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
13389 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
13404 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13416 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
13428 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
13429 ", may be before timetable start time");
13440 AnsiString LastLocationName =
"";
13444 bool LastEntryIsAnArrival =
false;
13449 LastEntryIsAnArrival =
false;
13450 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13451 if(LastLocationName !=
"")
13453 throw Exception(
"Timetable error, moving Snt entry has LocationName set for " + TDEntry.
HeadCode);
13455 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
13468 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13480 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13493 TwoLocationFlag =
true;
13498 LastEntryIsAnArrival =
false;
13502 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13505 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13510 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
13513 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
13519 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13525 LastEntryIsAnArrival =
true;
13526 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
13527 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13539 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13551 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
13564 TwoLocationFlag =
true;
13569 LastEntryIsAnArrival =
false;
13573 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
13576 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
13584 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
13591 LastEntryIsAnArrival = !LastEntryIsAnArrival;
13599 AnsiString LocationNameToBeChecked =
"";
13604 unsigned int y = 0;
13618 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
13619 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
13637 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
13646 TwoLocationFlag =
true;
13657 if(TwoLocationFlag)
13667 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13672 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat entry doesn't have a location name set for " + TDEntry.
HeadCode);
13674 AnsiString LocName =
"";
13680 throw Exception(
"Error, 'Snt' entry at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
13687 throw Exception(
"Error, 'Snt' unlocated entry has a location name set for " + TDEntry.
HeadCode);
13710 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13735 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13757 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13779 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13798 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13801 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
13816 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13821 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
13825 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
13829 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
13833 throw Exception(
"Error - timetable ActionVector entry no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
13872 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13874 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
13880 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
13893 int IncMinutes = 0;
13903 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13909 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
13915 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
13920 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13926 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
13931 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat entry time exceeds 95h 59m, see service " + HC);
13944 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13970 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
13978 if(HeadCode.Length() > 4)
13980 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
13991 int ForwardCount = 0;
13992 int ReverseCount = 0;
13994 if(MainHeadCode == SecondHeadCode)
13996 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
14005 if(TDEntry.
HeadCode == MainHeadCode)
14007 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14022 if(ForwardCount == 0)
14025 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
14027 if(ForwardCount > 2)
14030 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
14031 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14040 if(TDEntry.
HeadCode == SecondHeadCode)
14042 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14057 if(ReverseCount == 0)
14059 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
14064 if(ReverseCount > 2)
14067 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
14068 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
14073 if(ForwardCount != ReverseCount)
14075 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
14076 " than the other way round");
14107 int ForwardCount = 0;
14108 int ReverseCount = 0;
14109 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
14118 if(TDEntry.
HeadCode == MainHeadCode)
14120 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14123 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14128 ForwardEntryPtr = &AVEntry;
14130 ForwardTDVectorNumber = x;
14133 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
14134 (AVEntry.
Command ==
"Frh-sh")))
14139 ForwardEntryPtr = &AVEntry;
14141 ForwardTDVectorNumber = x;
14147 if(ForwardCount == 0)
14150 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
14152 if(ForwardCount > 1)
14154 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
14164 if(TDEntry.
HeadCode == OtherHeadCode)
14166 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14169 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
14175 ReverseEntryPtr = &AVEntry;
14176 ReverseTDVectorNumber = x;
14179 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
14185 ReverseEntryPtr = &AVEntry;
14186 ReverseTDVectorNumber = x;
14193 if(ReverseCount == 0)
14195 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
14200 if(ReverseCount > 1)
14202 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
14209 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
14210 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
14211 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
14212 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
14216 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
14223 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
14228 if(ForwardEntryPtr->LocationName ==
"")
14230 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14231 ". One or other service does not have a location set");
14238 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
14239 ". One or other service does not have a location set");
14244 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
14246 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14247 " is at a different location to the referencing train " + MainHeadCode);
14255 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
14257 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
14258 " has a different event time to the referencing train " + MainHeadCode);
14266 if(ForwardShuttleStart && ReverseShuttleFinish)
14271 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
14272 " first repeat restart time not consistent with finish service " + OtherHeadCode);
14278 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
14281 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14283 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
14284 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14290 if(ReverseEntryPtr->
Command ==
"Fjo")
14293 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14295 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
14296 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14302 if(ReverseEntryPtr->
Command ==
"Fns")
14305 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
14307 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
14308 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
14314 if(ForwardEntryPtr->Command ==
"Sfs")
14316 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
14319 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
14326 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
14328 if(ReverseEntryPtr->
Command !=
"Sfs")
14330 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
14340 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
14347 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
14354 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
14359 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14370 if(ForwardEntryPtr->Command ==
"Sns")
14372 if(ReverseEntryPtr->
Command !=
"Fns")
14374 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
14375 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
14381 if(ForwardEntryPtr->Command ==
"Fns")
14383 if(ReverseEntryPtr->
Command !=
"Sns")
14385 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
14386 " and forms a new service with headcode " + OtherHeadCode);
14393 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14404 if(ForwardEntryPtr->Command ==
"jbo")
14406 if(ReverseEntryPtr->
Command !=
"Fjo")
14408 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
14409 " and is joined by a train with headcode " + OtherHeadCode);
14415 if(ForwardEntryPtr->Command ==
"Fjo")
14417 if(ReverseEntryPtr->
Command !=
"jbo")
14419 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
14420 " and joins a train with headcode " + OtherHeadCode);
14427 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14437 if(ForwardShuttleStart)
14440 if(!ReverseShuttleFinish)
14443 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
14444 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
14450 if(ReverseShuttleStart)
14453 if(!ForwardShuttleFinish)
14456 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
14457 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
14464 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
14476 bool MainRepeat =
false, OtherRepeat =
false;
14486 OtherRepeat =
true;
14489 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
14491 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
14492 " and the associated train with headcode " + OtherHeadCode);
14497 if(MainRepeat && OtherRepeat)
14503 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
14504 " and the associated train with headcode " + OtherHeadCode);
14526 while(Input[1] ==
' ')
14528 if(Input.Length() > 1)
14530 Input = Input.SubString(2, Input.Length() - 1);
14544 while(Input[Input.Length()] ==
' ')
14546 if(Input.Length() > 1)
14548 Input = Input.SubString(1, Input.Length() - 1);
14558 AnsiString Output =
"";
14559 bool DelimiterFound =
false;
14561 for(
int x = 1; x < Input.Length() + 1; x++)
14565 if(Input[x] ==
' ')
14570 if((Input[x] !=
',') && (Input[x] !=
';'))
14572 DelimiterFound =
false;
14573 Output = Output + Input[x];
14577 DelimiterFound =
true;
14578 Output = Output + Input[x];
14590 DelimiterFound =
false;
14591 for(
int x = Input.Length(); x > 0; x--)
14595 if(Input[x] ==
' ')
14600 if((Input[x] !=
',') && (Input[x] !=
';'))
14602 DelimiterFound =
false;
14603 Output = AnsiString(Input[x]) + Output;
14607 DelimiterFound =
true;
14608 Output = AnsiString(Input[x]) + Output;
14633 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
14635 throw Exception(
"Error, first entry not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
14647 LocationName = LocRear;
14651 LocationName = LocFront;
14653 if(LocationName ==
"")
14674 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
14715 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
14718 if(RearPosition < 0)
14725 if(FrontPosition < 0)
14736 for(
int x = 0; x < 4; x++)
14738 if(RearTrackElement.
Conn[x] == FrontPosition)
14753 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
14760 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
14766 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
14771 if((RearType ==
Points) && (RearExitPos == 3))
14773 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
14779 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
14794 AnsiString(RearExitPos));
14805 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
14807 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
14810 AnsiString RearName, FrontName;
14826 FrontName = FrontTrackElement.
ElementID;
14829 int LockedVectorNumber;
14999 "," + AnsiString(IncDigits));
15002 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
15007 return(BaseHeadCode);
15009 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
15010 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
15012 while(NextRepeatDigits >= 100)
15014 NextRepeatDigits -= 100;
15016 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
15018 if(NextRepeatDigitsStr.Length() < 2)
15020 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
15022 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
15025 return(NextRepeatHeadCode);
15033 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
15034 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
15036 return(NextRepeatTime);
15045 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
15046 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15047 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15048 int RepeatSecs = RepeatMinutes * 60;
15050 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
15085 NonRepeatingHeadCode);
15086 int ForwardCount = 0;
15087 int ReverseCount = 0;
15088 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15098 if(TDEntry.
HeadCode == MainHeadCode)
15100 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15106 ForwardEntryPtr = &AVEntry;
15108 ForwardTDVectorNumber = x;
15113 if(ForwardCount == 0)
15116 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
15118 if(ForwardCount > 1)
15120 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
15130 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
15132 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15139 ReverseEntryPtr = &AVEntry;
15140 ReverseTDVectorNumber = x;
15146 if(ReverseCount == 0)
15148 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
15153 if(ReverseCount > 1)
15155 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15156 NonRepeatingHeadCode);
15161 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
15163 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
15168 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
15170 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
15175 if(ForwardEntryPtr->LocationName ==
"")
15177 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15178 ". One or other service does not have a location set");
15185 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
15186 ". One or other service does not have a location set");
15191 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15193 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
15194 " is at a different location to the referencing train " + MainHeadCode);
15199 if(ForwardEntryPtr->Command ==
"F-nshs")
15202 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15204 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
15205 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
15211 if(ForwardEntryPtr->Command ==
"Fns-sh")
15215 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
15217 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
15218 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
15224 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
15227 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15229 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
15230 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
15248 if(ForwardEntryPtr->Command ==
"Sns-sh")
15250 if(ReverseEntryPtr->
Command !=
"F-nshs")
15252 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
15253 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
15259 if(ForwardEntryPtr->Command ==
"F-nshs")
15261 if(ReverseEntryPtr->
Command !=
"Sns-sh")
15263 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
15264 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
15271 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15282 if(ForwardEntryPtr->Command ==
"Sns-fsh")
15284 if(ReverseEntryPtr->
Command !=
"Fns-sh")
15287 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
15288 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
15294 if(ForwardEntryPtr->Command ==
"Fns-sh")
15296 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
15299 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
15300 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
15307 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
15331 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
15332 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
15333 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
15334 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
15336 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
15360 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
15363 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
15364 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15366 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15368 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15373 while(LastActionCommand ==
"Fns")
15375 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
15376 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
15377 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
15380 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
15381 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
15388 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
15391 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
15392 ". The linking of two or more shuttles is not permitted.");
15412 ShowMessage(Message);
15430 ShowMessage(Message);
15469 AnsiString(ActionEventType) +
"," + LocationID);
15470 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
15475 Prefix =
" ERROR: ";
15478 Prefix =
" HELD: ";
15479 ErrorLog =
" can't enter railway, train obstructing entry position ";
15480 WarningStr =
" can't enter railway, train obstructing entry position ";
15485 Prefix =
" HELD: ";
15486 ErrorLog =
" can't enter railway, route set against it at entry position ";
15487 WarningStr =
" can't enter railway, route set against it at entry position ";
15492 Prefix =
" HELD: ";
15493 ErrorLog =
" can't be created, train obstructing ";
15494 WarningStr =
" can't be created, train obstructing ";
15499 Prefix =
" HELD: ";
15500 ErrorLog =
" can't be created on a locked route at ";
15501 WarningStr =
" can't be created on a locked route at ";
15506 Prefix =
" HELD: ";
15507 ErrorLog =
" can't enter on a locked route at ";
15508 WarningStr =
" can't enter on a locked route at ";
15513 Prefix =
" HELD: ";
15514 ErrorLog =
" can't be created, diverging points at ";
15515 WarningStr =
" can't be created, diverging points at ";
15520 ErrorLog =
" left railway unexpectedly at ";
15525 ErrorLog =
" left railway at an incorrect exit at ";
15530 ErrorLog =
" failed to split - location too short at ";
15531 WarningStr =
" failed to split, location too short at ";
15536 Prefix =
" HELD: ";
15537 ErrorLog =
" unable to split - other train obstructing at ";
15538 WarningStr =
" unable to split - other train obstructing at ";
15543 ErrorLog =
" stopped at buffers unexpectedly at position ";
15547 ErrorLog =
" failed to stop at ";
15552 ErrorLog =
" failed to split at ";
15557 ErrorLog =
" failed to be joined by other train at ";
15562 ErrorLog =
" failed to join other train at ";
15567 ErrorLog =
" failed to terminate at ";
15572 ErrorLog =
" failed to form new service at ";
15577 ErrorLog =
" failed to exit railway ";
15582 ErrorLog =
" failed to change direction at ";
15587 ErrorLog =
" failed to pass ";
15592 ErrorLog =
" facing buffers and unable to start at ";
15596 ErrorLog =
" DERAILED at position ";
15597 Prefix =
" DERAILMENT: ";
15602 ErrorLog =
" CRASHED INTO BUFFERS at ";
15603 Prefix =
" CRASH: ";
15608 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
15609 Prefix =
" CRASH: ";
15614 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
15615 Prefix =
" CRASH: ";
15619 else if(ActionEventType ==
FailSPAD)
15621 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
15622 Prefix =
" SPAD: ";
15627 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
15628 Prefix =
" SPAD RISK: ";
15633 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
15637 Prefix =
" WARNING: ";
15638 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
15639 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
15644 Prefix =
" WARNING: ";
15645 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
15646 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
15684 std::ofstream OutFile(
"TrainData.csv");
15688 ShowMessage(
"Output file TrainData.csv failed to open");
15695 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
15700 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
15701 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
15702 "RepeatNumber" <<
'\n' <<
'\n';
15703 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15706 AnsiString TimetableEntryTypeStr;
15712 TimetableEntryTypeStr =
"NoFormat";
15718 TimetableEntryTypeStr =
"TimeLoc";
15724 TimetableEntryTypeStr =
"TimeTimeLoc";
15730 TimetableEntryTypeStr =
"TimeCmd";
15736 TimetableEntryTypeStr =
"StartNew";
15742 TimetableEntryTypeStr =
"TimeCmdHeadCode";
15748 TimetableEntryTypeStr =
"FinRemHere";
15754 TimetableEntryTypeStr =
"FNSShuttle";
15760 TimetableEntryTypeStr =
"SNTShuttle";
15766 TimetableEntryTypeStr =
"SNSShuttle";
15772 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
15778 TimetableEntryTypeStr =
"FSHNewService";
15784 TimetableEntryTypeStr =
"Repeat";
15790 TimetableEntryTypeStr =
"Default";
15801 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
15802 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
15805 AnsiString RunningEntryStr;
15811 RunningEntryStr =
"NotStarted";
15817 RunningEntryStr =
"Running";
15823 RunningEntryStr =
"Exited";
15827 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
15844 ShowMessage(Message);
15845 BaseTime = TDateTime::CurrentDateTime();
15859 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
15872 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15874 for(
int x = 0; x < NumberOfTrains; x++)
15876 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
15896 int NumberOfTrains;
15903 for(
int x = 0; x < NumberOfTrains; x++)
15940 for(
int x = 0; x < LockedRouteVectorSize; x++)
15947 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
15958 int LockedRouteVectorSize;
15965 for(
int x = 0; x < LockedRouteVectorSize; x++)
16023 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16031 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
16042 int ContinuationAutoSigVectorSize;
16049 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
16119 if(AVFirstEntry.
Command ==
"Snt")
16143 CTEMMP.second = CTEEntry;
16150 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
16158 CTEMMP.second = CTEEntry;
16179 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16196 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
16198 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
16209 AnsiString RetStr =
"", PartStr =
"";
16324 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16328 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
16330 AnsiString ShortTTName =
"";
16332 for(
int x = TTFileName.Length(); x > 0; x--)
16334 if(TTFileName[x] ==
'\\')
16336 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
16341 ShowMessage(
"Creates two timetables named " + ShortTTName +
16342 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
16344 Screen->Cursor = TCursor(-11);
16346 AnsiString FormatNoDPStr =
"#######0";
16347 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
16350 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
16357 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
16359 if(TrainDataEntry.
Mass > 0)
16361 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
16365 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
16369 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
16373 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
16375 FirstHeadCode = TrainDataEntry.
HeadCode;
16376 int IncDigits = 0, IncMinutes = 0;
16378 if(!ActionVector.empty())
16380 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
16382 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
16383 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
16391 if((TrainDataEntry.
Description !=
"") && (MassStr !=
""))
16393 OneTTLine.
Header = TrainDataEntry.
Description + MassStr + PowerStr + BrakeStr + MaxSpeedStr;
16401 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16406 AnsiString PartStr =
"", TimeStr =
"";
16423 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16427 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
16437 PartStr =
"Enters at " + LocName;
16450 PartStr =
"Created at " + LocName;
16464 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
16469 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16475 else if(ActionVectorEntry.
Command ==
"Sfs")
16477 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
16481 else if(ActionVectorEntry.
Command ==
"Sns")
16483 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16491 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16497 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
16505 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
16508 AnsiString FirstHeadCode = TDE->
HeadCode;
16512 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
16524 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16526 OneTTEntry.
Action = PartStr;
16527 OneTTEntry.
Time = TimeStr;
16529 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16534 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
16540 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
16545 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
16553 else if(ActionVectorEntry.
Command ==
"jbo")
16555 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
16559 else if(ActionVectorEntry.
Command ==
"fsp")
16561 PartStr =
"Splits from front at " + ActionVectorEntry.
LocationName +
" to form";
16565 else if(ActionVectorEntry.
Command ==
"rsp")
16567 PartStr =
"Splits from rear at " + ActionVectorEntry.
LocationName +
" to form";
16571 else if(ActionVectorEntry.
Command ==
"cdt")
16573 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
16579 if(ActionVectorEntry.
Command ==
"Fns")
16581 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16585 else if(ActionVectorEntry.
Command ==
"F-nshs")
16587 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16593 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
16600 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16606 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
16613 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
16618 else if(ActionVectorEntry.
Command ==
"Frh")
16620 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
16625 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
16629 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
16639 else if(ActionVectorEntry.
Command ==
"Fer")
16641 AnsiString AllowedExits;
16645 else if(ActionVectorEntry.
Command ==
"Fjo")
16647 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
16656 OneTTEntry.
Action = PartStr;
16657 OneTTEntry.
Time = TimeStr;
16664 AllTTTrains->push_back(OneTTLine);
16668 std::ofstream TTFile(TTFileName.c_str());
16672 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
16673 delete AllTTTrains;
16708 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
16709 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16711 TTFile << AllTTTrains->at(x).Header.c_str();
16714 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16716 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16718 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
16722 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
16725 TTFile <<
'\n' <<
'\n';
16727 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
16729 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
16730 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16732 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
16734 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
16738 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
16743 TTFile <<
'\n' <<
'\n';
16748 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
16750 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
16752 std::ofstream TTFile2(TTFileName2.c_str());
16756 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
16757 delete AllTTTrains;
16761 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
16762 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
16763 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
16765 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
16770 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
16771 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
16773 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
16775 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
16777 bool GiveMessagesFalse =
false;
16778 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
16779 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
16780 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
16785 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
16786 TimeString = TimeString.SubString(9, 5);
16787 ActionString +=
" " + OtherHeadCode;
16789 if(TimeString.SubString(1, 7) ==
"End at ")
16792 TimeString = TimeString.SubString(8, 5);
16794 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
16795 AnsiMultiMapEntry.first = TimeString;
16796 AnsiMultiMapEntry.second = OneLine;
16797 TAMM->insert(AnsiMultiMapEntry);
16802 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
16804 TTFile2 << (AMMIT->second).c_str();
16806 delete AllTTTrains;
16815 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
16819 bool AnalysisError =
false;
16820 AnsiString SequenceLog =
"SequenceLog\n";
16862 TTrainDataVector::iterator TDVIt, TDVCopyIt;
16864 int IteratorNumber = 0;
16865 AnsiString AnsiSuffix =
"";
16870 for(TDVCopyIt = TrainDataVectorCopy.begin() + IteratorNumber; TDVCopyIt != TrainDataVectorCopy.end(); TDVCopyIt++)
16872 if(TDVCopyIt->ServiceReference == TDVIt->ServiceReference)
16875 AnsiSuffix = AnsiString(Suffix);
16876 TDVCopyIt->ServiceReference = TDVIt->ServiceReference +
"/" + AnsiSuffix;
16880 SequenceLog +=
"1\n";
16883 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
16884 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
16889 ServiceCallingLocsList.clear();
16890 if(ActionVector.empty())
16894 if(ActionVector.at(0).SignallerControl)
16898 for(
unsigned int z = 0; z < ActionVector.size(); z++)
16916 int HLoc = TE.
HLoc;
16917 int VLoc = TE.
VLoc;
16918 AnsiString HString;
16919 AnsiString VString;
16922 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16926 HString = AnsiString(HLoc);
16930 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
16934 VString = AnsiString(VLoc);
16936 ServiceCallingLocsList.push_back(HString +
'-' + VString);
16959 else if(AVE.
Command ==
"cdt")
16961 if(ActionVector.at(z-1).SequenceType ==
Start)
16965 else if(ActionVector.at(z+1).SequenceType ==
Finish)
16972 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
16981 ServiceCallingLocsList.push_back(LName);
16985 int HLoc = TE.
HLoc;
16986 int VLoc = TE.
VLoc;
16987 AnsiString HString;
16988 AnsiString VString;
16991 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
16995 HString = AnsiString(HLoc);
16999 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17003 VString = AnsiString(VLoc);
17005 ServiceCallingLocsList.push_back(HString +
'-' + VString);
17009 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
17013 SequenceLog +=
"2\n";
17042 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
17048 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
17049 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
17050 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
17052 SequenceLog +=
"3\n";
17054 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17059 TDateTime LastTDTime;
17060 int IncMinutes = 0;
17062 if(ActionVector.empty())
17066 if(ActionVector.at(0).SignallerControl)
17070 if(AVLast->FormatType ==
Repeat)
17072 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17080 if(AVLast->ArrivalTime != TDateTime(-1))
17082 LastTDTime = AVLast->ArrivalTime;
17084 else if(AVLast->EventTime != TDateTime(-1))
17086 LastTDTime = AVLast->EventTime;
17105 SequenceLog +=
"4\n";
17137 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
17142 int IncMinutes = 0;
17144 if(ActionVector.empty())
17148 if(ActionVector.at(0).SignallerControl)
17152 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17154 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17156 for(
int y = 0; y < NumTrains; y++)
17170 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17185 LocServiceTimesVector.push_back(TLSTEntry);
17188 AnsiString IncTime =
"", FoundStopTime =
"";
17189 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17191 if(ActionVector.at(a).FormatType ==
TimeLoc)
17196 if(ActionVector.at(a).SequenceType ==
Finish)
17202 if(FoundStopTime ==
"")
17204 throw Exception(
"Failure to determine FoundStopTime for located Snt");
17206 int WhileCount = 0;
17215 if(IncTime >= FoundStopTime)
17219 LocServiceTimesVector.push_back(TLSTEntry);
17220 if(WhileCount > 2000)
17222 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
17235 int HLoc = TE.
HLoc;
17236 int VLoc = TE.
VLoc;
17237 AnsiString HString;
17238 AnsiString VString;
17241 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17245 HString = AnsiString(HLoc);
17249 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17253 VString = AnsiString(VLoc);
17255 TLSTEntry.
Location = HString +
'-' + VString;
17259 LocServiceTimesVector.push_back(TLSTEntry);
17267 LocServiceTimesVector.push_back(TLSTEntry);
17269 AnsiString IncTime =
"", FoundStopTime =
"";
17270 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17272 if(ActionVector.at(a).FormatType ==
TimeLoc)
17277 if(ActionVector.at(a).SequenceType ==
Finish)
17283 if(FoundStopTime ==
"")
17285 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
17287 int WhileCount = 0;
17296 if(IncTime >= FoundStopTime)
17300 LocServiceTimesVector.push_back(TLSTEntry);
17301 if(WhileCount > 2000)
17303 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17313 bool SkipAddingMinutes =
false;
17316 LocServiceTimesVector.push_back(TLSTEntry);
17318 AnsiString IncTime =
"", FoundStopTime =
"";
17319 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
17321 if(ActionVector.at(a).FormatType ==
TimeLoc)
17326 if(ActionVector.at(a).SequenceType ==
Finish)
17329 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr > 0) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr > 0)))
17333 LocServiceTimesVector.pop_back();
17334 SkipAddingMinutes =
true;
17339 if(FoundStopTime ==
"")
17341 throw Exception(
"Failure to determine FoundStopTime for SequenceType == Start");
17343 if(!SkipAddingMinutes)
17345 int WhileCount = 0;
17354 if(IncTime >= FoundStopTime)
17358 LocServiceTimesVector.push_back(TLSTEntry);
17359 if(WhileCount > 2000)
17361 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == Start");
17370 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
17372 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
17374 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
17375 LocServiceTimesVector.pop_back();
17376 LocServiceTimesVector.push_back(TLSTEntry);
17381 LocServiceTimesVector.push_back(TLSTEntry);
17387 LocServiceTimesVector.push_back(TLSTEntry);
17406 LocServiceTimesVector.push_back(TLSTEntry);
17410 AnsiString TempDepTime = TLSTEntry.
DepTime;
17412 LocServiceTimesVector.push_back(TLSTEntry);
17414 while(TLSTEntry.
AtLocTime < TempDepTime)
17419 TLSTEntry.
DepTime = TempDepTime;
17420 LocServiceTimesVector.push_back(TLSTEntry);
17424 LocServiceTimesVector.push_back(TLSTEntry);
17435 LocServiceTimesVector.push_back(TLSTEntry);
17438 LocServiceTimesVector.push_back(TLSTEntry);
17455 AnsiString HString;
17456 AnsiString VString;
17459 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
17463 HString = AnsiString(HLoc);
17467 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
17471 VString = AnsiString(VLoc);
17473 TLSTEntry.
Location = HString +
'-' + VString;
17475 LocServiceTimesVector.push_back(TLSTEntry);
17480 AnsiString FrhTime;
17481 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17485 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17493 LocServiceTimesVector.push_back(TLSTEntry);
17499 LocServiceTimesVector.push_back(TLSTEntry);
17504 else if(AVE.
Command ==
"Frh-sh")
17506 if(y == NumTrains - 1)
17512 LocServiceTimesVector.push_back(TLSTEntry);
17518 LocServiceTimesVector.push_back(TLSTEntry);
17531 SequenceLog +=
"5\n";
17562 TLocServiceTimesVector::iterator Ptr1, Ptr2;
17565 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17566 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17568 std::ofstream TTFile3(TTFileName3.c_str());
17572 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
17576 if(LocServiceTimesVector.empty())
17578 ShowMessage(
"No timetabled services found");
17580 DeleteFile(TTFileName3);
17584 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
17585 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
17586 SequenceLog +=
"6\n";
17636 Ptr1 = LocServiceTimesVector.begin();
17638 while(Ptr2 != LocServiceTimesVector.end())
17640 while(Ptr2->Location == Ptr1->Location)
17643 if(Ptr2 == LocServiceTimesVector.end())
17650 if(Ptr2 != LocServiceTimesVector.end())
17658 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
17659 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17660 MinuteString =
" minutes";
17661 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17664 MinuteString =
" minute";
17666 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
17667 TTFile3 <<
",Platforms,Trains\n\n";
17669 Ptr1 = LocServiceTimesVector.begin();
17671 while(Ptr2 != LocServiceTimesVector.end())
17673 PreviousService =
"";
17674 NumTrainsAtLoc = 0;
17675 ServiceAndRepeatNumTotal =
"";
17677 NumPlatsAtThisLocCalculated =
false;
17679 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17681 PreviousService =
"";
17682 NumTrainsAtLoc = 0;
17683 ServiceAndRepeatNumTotal =
"";
17685 NumPlatsAtThisLocCalculated =
false;
17689 if(Ptr2 == LocServiceTimesVector.end())
17694 if(Ptr2 == LocServiceTimesVector.end())
17698 while(Ptr2->Location == Ptr1->Location)
17700 PreviousService =
"";
17701 NumTrainsAtLoc = 0;
17702 ServiceAndRepeatNumTotal =
"";
17703 BasicTime = Ptr1->ArrTime;
17704 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17708 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
17710 BasicTime = Ptr2->ArrTime;
17713 if(Ptr2 == LocServiceTimesVector.end())
17717 if(Ptr2->Location != Ptr1->Location)
17722 if(Ptr2 == LocServiceTimesVector.end())
17726 if(Ptr2->Location != Ptr1->Location)
17732 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
17736 if(!NumPlatsAtThisLocCalculated)
17739 NumPlatsAtThisLocCalculated =
true;
17741 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17743 if(ServiceAndRepeatNumTotal ==
"")
17745 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17746 NumTrainsAtLoc = 1;
17750 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
17753 PreviousService = Ptr2->ServiceAndRepeatNum;
17754 if(ServiceAndRepeatNumTotal ==
"")
17756 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17757 NumTrainsAtLoc = 1;
17761 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
17765 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
17767 int MaxNumberOfSameDirections = 0;
17768 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
17773 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17777 AnsiString Asterisk =
"";
17778 if(MaxNumberOfSameDirections >= NumPlats)
17783 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17784 ArrivalsPrinted =
true;
17785 ServiceAndRepeatNumTotal =
"";
17787 if(Ptr2 == LocServiceTimesVector.end())
17791 if(Ptr2->Location != Ptr1->Location)
17796 if(Ptr2 == LocServiceTimesVector.end())
17802 if(!ArrivalsPrinted)
17804 TTFile3 <<
"Nothing to report for arrivals";
17809 SequenceLog +=
"7\n";
17814 Ptr1 = LocServiceTimesVector.begin();
17816 while(Ptr2 != LocServiceTimesVector.end())
17818 while(Ptr2->Location == Ptr1->Location)
17821 if(Ptr2 == LocServiceTimesVector.end())
17828 if(Ptr2 != LocServiceTimesVector.end())
17835 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
17836 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
17837 MinuteString =
" minutes";
17838 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
17841 MinuteString =
" minute";
17843 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
17844 TTFile3 <<
",Platforms,Trains\n\n";
17846 Ptr1 = LocServiceTimesVector.begin();
17848 while(Ptr2 != LocServiceTimesVector.end())
17850 PreviousService =
"";
17851 NumTrainsAtLoc = 0;
17852 ServiceAndRepeatNumTotal =
"";
17854 NumPlatsAtThisLocCalculated =
false;
17856 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
17858 PreviousService =
"";
17859 NumTrainsAtLoc = 0;
17860 ServiceAndRepeatNumTotal =
"";
17862 NumPlatsAtThisLocCalculated =
false;
17866 if(Ptr2 == LocServiceTimesVector.end())
17871 if(Ptr2 == LocServiceTimesVector.end())
17875 while(Ptr2->Location == Ptr1->Location)
17877 PreviousService =
"";
17878 NumTrainsAtLoc = 0;
17879 ServiceAndRepeatNumTotal =
"";
17880 BasicTime = Ptr1->DepTime;
17881 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
17885 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
17887 BasicTime = Ptr2->DepTime;
17890 if(Ptr2 == LocServiceTimesVector.end())
17894 if(Ptr2->Location != Ptr1->Location)
17899 if(Ptr2 == LocServiceTimesVector.end())
17903 if(Ptr2->Location != Ptr1->Location)
17909 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
17913 if(!NumPlatsAtThisLocCalculated)
17916 NumPlatsAtThisLocCalculated =
true;
17918 if(Ptr1->ServiceAndRepeatNum != PreviousService)
17920 if(ServiceAndRepeatNumTotal ==
"")
17922 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17923 NumTrainsAtLoc = 1;
17927 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
17930 PreviousService = Ptr2->ServiceAndRepeatNum;
17931 if(ServiceAndRepeatNumTotal ==
"")
17933 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17934 NumTrainsAtLoc = 1;
17938 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
17942 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
17944 int MaxNumberOfSameDirections = 0;
17945 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
17950 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
17954 AnsiString Asterisk =
"";
17955 if(MaxNumberOfSameDirections >= NumPlats)
17960 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
17961 DeparturesPrinted =
true;
17962 ServiceAndRepeatNumTotal =
"";
17964 if(Ptr2 == LocServiceTimesVector.end())
17968 if(Ptr2->Location != Ptr1->Location)
17973 if(Ptr2 == LocServiceTimesVector.end())
17979 if(!DeparturesPrinted)
17981 TTFile3 <<
"Nothing to report for departures";
17986 SequenceLog +=
"8\n";
17993 Ptr1 = LocServiceTimesVector.begin();
17995 while(Ptr2 != LocServiceTimesVector.end())
17997 while(Ptr2->Location == Ptr1->Location)
18000 if(Ptr2 == LocServiceTimesVector.end())
18007 if(Ptr2 != LocServiceTimesVector.end())
18014 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
18015 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
18016 TTFile3 <<
",Platforms,Trains,\n\n";
18017 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
18018 Ptr1 = LocServiceTimesVector.begin();
18020 while(Ptr2 != LocServiceTimesVector.end())
18022 PreviousService =
"";
18023 ServiceAndRepeatNumTotal =
"";
18024 NumTrainsAtLoc = 0;
18026 NumPlatsAtThisLocCalculated =
false;
18029 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
18031 PreviousService =
"";
18032 ServiceAndRepeatNumTotal =
"";
18033 NumTrainsAtLoc = 0;
18035 NumPlatsAtThisLocCalculated =
false;
18039 if(Ptr2 == LocServiceTimesVector.end())
18044 if(Ptr2 == LocServiceTimesVector.end())
18048 while(Ptr2->Location == Ptr1->Location)
18050 if(Ptr1->FrhMarker ==
"Frh")
18053 Ptr1->FrhMarker =
"FrhCounted";
18055 PreviousService =
"";
18056 NumTrainsAtLoc = 0;
18057 ServiceAndRepeatNumTotal =
"";
18058 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
18062 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
18065 if(Ptr1->FrhMarker ==
"Frh")
18068 Ptr1->FrhMarker =
"FrhCounted";
18071 if(Ptr2 == LocServiceTimesVector.end())
18075 if(Ptr2->Location != Ptr1->Location)
18080 if(Ptr2 == LocServiceTimesVector.end())
18084 if(Ptr2->Location != Ptr1->Location)
18088 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
18090 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
18094 if(!NumPlatsAtThisLocCalculated)
18097 NumPlatsAtThisLocCalculated =
true;
18099 if(Ptr1->ServiceAndRepeatNum != PreviousService)
18101 if(ServiceAndRepeatNumTotal ==
"")
18103 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
18104 NumTrainsAtLoc = 1;
18108 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
18111 PreviousService = Ptr2->ServiceAndRepeatNum;
18112 if(ServiceAndRepeatNumTotal ==
"")
18114 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
18115 NumTrainsAtLoc = 1;
18119 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
18122 if(Ptr1->FrhMarker ==
"Frh")
18125 Ptr1->FrhMarker =
"FrhCounted";
18128 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
18132 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
18134 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
18136 AnsiString Asterisk =
"";
18137 if(NumTrainsAtLoc > NumPlats)
18144 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
18146 else if(FrhCount == 1)
18148 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
18152 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
18154 LastFrhCount = FrhCount;
18155 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
18156 AtLocsPrinted =
true;
18157 ServiceAndRepeatNumTotal =
"";
18160 if(Ptr2 == LocServiceTimesVector.end())
18164 if(Ptr2->Location != Ptr1->Location)
18169 if(Ptr2 == LocServiceTimesVector.end())
18177 TTFile3 <<
"Nothing to report for trains at locations";
18182 SequenceLog +=
"9\n";
18212 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
18217 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
18218 for(
unsigned int x = 0; x < TrainDataVectorCopy.size(); x++)
18226 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
18228 SingleServiceEntry = TDE;
18230 for(
unsigned int y = 0; y < SSAV.size(); y++)
18232 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
18234 SingleServiceVector.push_back(SingleServiceEntry);
18237 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
18239 PartServiceEntry = TDE;
18241 for(
unsigned int z = 0; z <= y; z++)
18246 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
18247 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
18250 PartServiceVector.push_back(PartServiceEntry);
18251 if(SSAV.at(y).Command ==
"fsp")
18253 SSAV.at(y).Command =
"Front split - original service continues below";
18254 SSAV.at(y).OtherHeadCode =
"";
18256 if(SSAV.at(y).Command ==
"rsp")
18258 SSAV.at(y).Command =
"Rear split - original service continues below";
18259 SSAV.at(y).OtherHeadCode =
"";
18263 else if(SSAV.at(y).Command ==
"Fns")
18265 SSAV.at(y).Command =
"chr-Fns";
18266 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
18267 PartServiceVector.push_back(SingleServiceEntry);
18270 else if(SSAV.at(y).Command ==
"Fns-sh")
18272 SSAV.at(y).Command =
"chr-Fns-sh";
18273 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18274 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18275 PartServiceVector.push_back(SingleServiceEntry);
18278 else if(SSAV.at(y).Command ==
"F-nshs")
18280 SSAV.at(y).Command =
"chr-F-nshs";
18281 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
18282 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18283 PartServiceVector.push_back(SingleServiceEntry);
18289 SequenceLog +=
"10\n";
18293 AnsiString NextRef;
18294 while(!PartServiceVector.empty())
18296 PartServiceEntry = PartServiceVector.at(0);
18297 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
18299 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
18301 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
18305 bool FinishType =
true, FoundFlag =
false;
18312 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
18316 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18320 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18326 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18327 SingleServiceVector.push_back(PartServiceVector.at(0));
18328 PartServiceVector.erase(&PartServiceVector.at(0));
18333 NewPartServiceEntry = PartServiceVector.at(0);
18337 PartServiceVector.push_back(NewPartServiceEntry);
18340 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
18345 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
18348 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18350 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
18353 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18355 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18358 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
18361 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18362 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18363 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
18364 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18367 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
18371 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
18372 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
18373 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
18381 SequenceLog += +
"11\n";
18382 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
18386 if(!PartServiceVector.empty())
18388 SequenceLog +=
"12\n";
18389 throw Exception(
"PartServiceVector should be empty here - size = " + PartServiceVector.size());
18391 SequenceLog +=
"13\n";
18436 bool BufferFacingUnReportedFlag =
true;
18437 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18443 SequenceLog +=
"13a\n";
18444 throw Exception(
"Repeat entry present in SingleServiceVector at position " + x);
18447 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
18449 bool BufferFlag =
false;
18450 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
18451 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
18452 AnsiString FrontLocName = AV.at(0).LocationName;
18453 int NextEntryPos, NextExitPos;
18456 if(ThisElement.
Conn[0] == RearTVPos)
18460 else if(ThisElement.
Conn[1] == RearTVPos)
18464 else if(ThisElement.
Conn[2] == RearTVPos)
18468 else if(ThisElement.
Conn[3] == RearTVPos)
18480 if(ThisElement.
Conn[ThisExitPos] == -1)
18482 SequenceLog =
"13b\n";
18483 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
18486 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
18487 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
18489 BufferFlag =
false;
18494 BufferFlag =
false;
18499 BufferFlag =
false;
18507 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
18509 ThisElement = NextElement;
18515 if(NextEntryPos == 0)
18519 else if(NextEntryPos == 1)
18523 else if(NextEntryPos == 2)
18527 else if(NextEntryPos == 3)
18532 ThisElement = NextElement;
18533 ThisExitPos = NextExitPos;
18538 if(BufferFacingUnReportedFlag)
18540 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
18541 BufferFacingUnReportedFlag =
false;
18543 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
18547 if(BufferFacingUnReportedFlag)
18549 TTFile3 <<
"Nothing to report for train facing directions\n\n";
18555 SequenceLog +=
"13c\n";
18558 AnsiString LocationNameToBeChecked =
"";
18559 bool MissingcdtUnreportedFlag =
true;
18561 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18564 unsigned int y = 0;
18565 int FirstInstance = 9999, SecondInstance = 9999;
18566 bool FullBreak =
false;
18567 MarkerList.clear();
18574 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
18583 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
18585 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
18590 (AVEntry.
Command ==
"Frh-sh"))
18605 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
18611 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
18613 SecondInstance = a;
18615 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18617 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18619 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18622 if(MissingcdtUnreportedFlag)
18624 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
18626 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
18627 MarkerList.push_back(FirstInstance);
18628 MarkerList.push_back(SecondInstance);
18630 MissingcdtUnreportedFlag =
false;
18641 if(MissingcdtUnreportedFlag)
18643 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
18649 SequenceLog +=
"14\n";
18658 typedef std::list<AnsiString> TLocList;
18659 TLocList BackwardList, ForwardList;
18660 bool IntroLineNeeded =
true;
18661 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
18663 unsigned int cdtPosition = 9999;
18664 AnsiString cdtLocation =
"";
18665 bool FoundSameName =
false;
18666 MarkerList.clear();
18668 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
18671 BackwardList.clear();
18672 ForwardList.clear();
18676 (AVEntry.
Command ==
"Frh-sh"))
18678 if(MarkerList.empty())
18685 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
18687 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
18689 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
18693 if(IntroLineNeeded)
18695 TTFile3 <<
"Questionable change of direction analysis.\n\n";
18696 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
18697 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
18698 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
18699 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
18700 IntroLineNeeded =
false;
18702 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
18714 for(
int z = y - 1; z >= 0; z--)
18717 if(AVEntry2.
Command ==
"cdt")
18726 BackwardList.sort();
18727 BackwardList.unique();
18728 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
18742 ForwardList.sort();
18743 ForwardList.unique();
18744 FoundSameName =
false;
18746 if(!BackwardList.empty() && !ForwardList.empty())
18748 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
18750 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
18754 FoundSameName =
true;
18761 MarkerList.push_back(cdtPosition);
18765 if(IntroLineNeeded)
18767 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
18783 SequenceLog +=
"15\n";
18789 catch(
const Exception &e)
18791 AnsiString TTErrorFileName =
"Analysis Error.txt";
18792 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
18793 std::ofstream TTError(TTErrorFileName.c_str());
18796 ShowMessage(
"Analysis error file failed to open - can't be created");
18800 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18801 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
18802 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
18805 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
18815 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
18817 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
18819 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
18821 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
18822 AnsiString Marker =
"";
18823 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
18826 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
18828 if(
int(x) == *MLIt)
18858 if(AVE.
Command.SubString(1,3) ==
"chr")
18867 AVE.
Command =
"Change of service to ";
18869 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
18871 AVE.
Command =
"Change to shuttle finishing service";
18873 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
18900 AnsiString ListOfExits =
"";
18909 VecFile << Marker <<
"Frh" <<
'\n';
18924 for(
unsigned int x = 0; x < Vector.size(); x++)
18928 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
18930 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
18933 FinishType =
false;
18938 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
18941 FinishType =
false;
18946 return(Vector.at(x));
18950 return(Vector.at(Vector.size() - 1));
18959 if((Time1 ==
"") || (Time2 ==
""))
18964 int Mins = Time1.SubString(4,2).ToInt();
18965 int Hours = Time1.SubString(1,2).ToInt();
18966 int Time1Mins = (Hours * 60) + Mins;
18967 Mins = Time2.SubString(4,2).ToInt();
18968 Hours = Time2.SubString(1,2).ToInt();
18969 int Time2Mins = (Hours * 60) + Mins;
18970 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
18982 bool &AnalysisError,
int &MaxNumberOfSameDirections)
18989 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
18991 std::list<AnsiString> ServiceList;
18993 bool EvenComma =
false;
18994 for(
int x = 1; x <= Input.Length(); x++)
18996 TempStr1 = Input[x];
18997 if(TempStr1 == AnsiString(
',') && EvenComma)
19003 TempStr2 += Input[x];
19005 if(TempStr1 == AnsiString(
','))
19007 EvenComma = !EvenComma;
19011 while(TempStr2.Length() > 0)
19013 SCPos = TempStr2.Pos(
';');
19016 OneService = TempStr2.SubString(1, SCPos - 1);
19017 ServiceList.push_back(OneService);
19018 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
19022 ServiceList.push_back(TempStr2);
19026 ServiceList.sort();
19027 ServiceList.unique();
19028 NumTrainsAtLoc = ServiceList.size();
19031 int DirectionMarker = 0;
19033 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
19035 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19037 *SLIt = *SLIt +
"&0";
19039 SLIt3 = ServiceList.end();
19041 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
19042 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
19043 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
19045 MaxNumberOfSameDirections = 0;
19046 int SameDirectionCount = 0;
19048 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
19052 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
19058 CommaPos1 = SLIt1->Pos(
',');
19059 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
19061 SpacePos = ServiceRef1.Pos(
' ');
19065 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
19066 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
19067 if(RepeatInfo1[1] ==
'F')
19073 SpacePos = RepeatInfo1.Pos(
' ');
19074 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
19077 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
19079 AmpersandPos = AnsiTime1.Pos(
'&');
19080 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
19085 throw Exception(
"ASCLIt1 Error in " + Input);
19087 ServiceCallingLocsList1 = ASCLIt1->second;
19088 AmpersandPos = SLIt1->Pos(
'&');
19089 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
19090 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
19092 SameDirectionCount = 1;
19093 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
19095 CommaPos2 = SLIt2->Pos(
',');
19096 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
19098 SpacePos = ServiceRef2.Pos(
' ');
19102 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
19103 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
19104 if(RepeatInfo2[1] ==
'F')
19110 SpacePos = RepeatInfo2.Pos(
' ');
19111 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
19114 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
19116 AmpersandPos = AnsiTime2.Pos(
'&');
19117 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
19122 throw Exception(
"ASCLIt2 Error in " + Input);
19124 ServiceCallingLocsList2 = ASCLIt2->second;
19126 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
19128 int AmpersandPos = SLIt2->Pos(
'&');
19129 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
19130 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
19131 SameDirectionCount++;
19134 if(SameDirectionCount > MaxNumberOfSameDirections)
19136 MaxNumberOfSameDirections = SameDirectionCount;
19141 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
19144 AmpersandPos = SLIt3->Pos(
'&');
19145 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
19146 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
19149 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19152 AmpersandPos = SLIt->Pos(
'&');
19153 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
19154 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
19155 DirectionMarker = DirectionMarkerString.ToInt();
19156 AnsiString DirectionSuffix =
"";
19158 if(DirectionMarker < 27)
19160 c = 64 + DirectionMarker;
19161 DirectionSuffix =
"," + AnsiString(c);
19163 else if(DirectionMarker < 53)
19165 c = 65 + DirectionMarker - 27;
19166 DirectionSuffix =
",A" + AnsiString(c);
19170 DirectionSuffix =
",?";
19172 *SLIt = ServiceWithoutMarker + DirectionSuffix;
19175 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19177 Output = Output + *SLIt +
",";
19179 if(Output.Length() > 0)
19181 Output = Output.SubString(1, Output.Length() - 1);
19187 catch(
const Exception &e)
19189 AnalysisError =
true;
19201 AnsiString InternalInput = Input, Output =
"", OneService =
"";
19203 std::list<AnsiString> ServiceList;
19205 while(InternalInput.Length() > 0)
19207 CommaPos = InternalInput.Pos(
',');
19210 OneService = InternalInput.SubString(1, CommaPos - 1);
19211 ServiceList.push_back(OneService);
19212 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
19216 ServiceList.push_back(InternalInput);
19217 InternalInput =
"";
19221 ServiceList.sort();
19222 ServiceList.unique();
19223 NumTrainsAtLoc = ServiceList.size();
19224 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
19226 Output = Output + *SLIt +
",";
19228 if(Output.Length() > 0)
19230 Output = Output.SubString(1, Output.Length() - 1);
19243 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
19245 std::list<AnsiString>::iterator LP1 = 0, LP2 = 0, ListPtr1 = 0, ListPtr2 = 0, LocPtr1 = 0, LocPtr2 = 0;
19250 bool LocFound =
false;
19251 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
19253 TDateTime FirstServiceTime;
19256 int Ref1Target = 0, Ref1Count = 0;
19257 int SlashPos = Ref1.Pos(
'/');
19260 Ref1Target = Ref1.SubString(SlashPos + 1, Ref1.Length() - SlashPos).ToInt();
19261 Ref1 = Ref1.SubString(1, SlashPos - 1);
19263 int Ref2Target = 0, Ref2Count = 0;
19264 SlashPos = Ref2.Pos(
'/');
19267 Ref2Target = Ref2.SubString(SlashPos + 1, Ref2.Length() - SlashPos).ToInt();
19268 Ref2 = Ref2.SubString(1, SlashPos - 1);
19270 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
19273 if((*ListPtr1) == Location)
19275 LocPtr1 = ListPtr1;
19278 if(ListPtr1->SubString(1, 3) ==
"%%%")
19280 AnsiString CDTTime = ListPtr1->SubString(4, 5);
19285 FirstServiceTime = TDateTime(-1);
19286 bool BreakFlag =
false;
19289 if(TDVIt->ServiceReference == Ref1)
19291 if(Ref1Target > Ref1Count)
19296 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
19297 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19301 FirstServiceTime = AVIt->EventTime;
19307 FirstServiceTime = AVIt->ArrivalTime;
19313 FirstServiceTime = AVIt->DepartureTime;
19324 if(IncMinutes == -1)
19326 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19328 if(FirstServiceTime == TDateTime(-1))
19330 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19334 if(!Arrival && (Time1 == CDTTime))
19339 if(Arrival && (Time1 == CDTTime))
19343 if(Time1 > CDTTime)
19348 if(Time1 < CDTTime)
19361 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
19363 if((*ListPtr2) == Location)
19365 LocPtr2 = ListPtr2;
19368 if(ListPtr2->SubString(1, 3) ==
"%%%")
19370 AnsiString CDTTime = ListPtr2->SubString(4, 5);
19375 FirstServiceTime = TDateTime(-1);
19376 bool BreakFlag =
false;
19379 if(TDVIt->ServiceReference == Ref2)
19381 if(Ref2Target > Ref2Count)
19386 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
19387 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
19391 FirstServiceTime = AVIt->EventTime;
19397 FirstServiceTime = AVIt->ArrivalTime;
19403 FirstServiceTime = AVIt->DepartureTime;
19414 if(IncMinutes == -1)
19416 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19418 if(FirstServiceTime == TDateTime(-1))
19420 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
19424 if(!Arrival && (Time2 == CDTTime))
19429 if(Arrival && (Time2 == CDTTime))
19433 if(Time2 > CDTTime)
19438 if(Time2 < CDTTime)
19453 LP1 = List1.begin();
19455 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
19457 if(ListPtr1 == List1.begin())
19461 if(ListPtr1->SubString(1, 3) ==
"%%%")
19468 LP2 = List2.begin();
19470 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
19472 if(ListPtr2 == List2.begin())
19476 if(ListPtr2->SubString(1, 3) ==
"%%%")
19486 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19488 if(ListPtr1 == LocPtr1)
19492 if(ListPtr1->SubString(1, 3) ==
"%%%")
19496 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19498 if(ListPtr2 == LocPtr2)
19502 if(ListPtr2->SubString(1, 3) ==
"%%%")
19506 if((*ListPtr1) == (*ListPtr2))
19523 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
19525 if(ListPtr1 == List1.end())
19529 if(ListPtr1->SubString(1, 3) ==
"%%%")
19533 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
19535 if(ListPtr2 == List2.end())
19539 if(ListPtr2->SubString(1, 3) ==
"%%%")
19543 if((*ListPtr1) == (*ListPtr2))
19560 if(ExitList.empty())
19566 AnsiString ExitLocList =
"";
19569 unsigned int Counter = 0;
19570 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
19574 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
19576 ExitLocList +=
"\n";
19579 if(StartName ==
"")
19581 if(ExitList.size() == 1)
19585 return(
" at " + ID);
19590 if(ExitList.size() < 4)
19592 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19597 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19602 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
19607 if(ExitList.size() < 4)
19609 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19614 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19620 if(ExitList.size() < 4)
19622 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
19623 return(
" at " + StartName);
19627 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
19628 return(
" at " + StartName);
19668 AnsiString FormatStr =
"####0.0";
19669 AnsiString AvLateArrMins =
"";
19670 AnsiString AvEarlyArrMins =
"";
19671 AnsiString AvLatePassMins =
"";
19672 AnsiString AvEarlyPassMins =
"";
19673 AnsiString AvLateDepMins =
"";
19674 AnsiString AvLateExitMins =
"";
19675 AnsiString AvEarlyExitMins =
"";
19678 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
19711 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
19712 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
19724 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19728 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
19736 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19740 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
19748 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
19756 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19760 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
19764 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
19768 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19772 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
19776 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
19781 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
19785 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
19789 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19793 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
19797 PerfFile <<
LateExits <<
" late exits" <<
'\n';
19801 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19805 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
19809 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
19814 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
19818 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
19822 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19826 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
19830 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
19832 TDateTime TempExcessLCDownTime;
19846 if(TempExcessLCDownTime > TDateTime(0))
19852 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
19856 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
19864 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
19868 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
19904 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
19908 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
19914 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
19918 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
19921 AnsiString AvLateMinsLocsNotReached =
"";
19927 if(LocsNotReached > 0)
19930 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
19934 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
19938 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
19950 PerfFile <<
Derailments <<
" derailments" <<
'\n';
19954 PerfFile <<
Derailments <<
" derailment" <<
'\n';
19964 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
19966 bool DerailSPADFlag =
false, CrashFlag =
false;
19968 int OverallScorePercent = 100;
19969 int TotArrDepExit = 0;
19970 double TotLateMinsFactor = 1;
19971 double MissedStopAndSPADRiskFactor = 1;
19972 double NetNegFactor = 1;
19982 OverallScorePercent = 5;
19983 DerailSPADFlag =
true;
19987 OverallScorePercent = 0;
19990 if(OverallScorePercent == 100)
19995 LatenessPenalty = 0;
20001 if(TotArrDepExit > 0)
20010 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
20012 OverallScorePercent = 100 * NetNegFactor;
20015 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
20018 AnsiString OneFailureString =
", though the failure would account for some poor performance";
20019 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
20020 AnsiString AddedString =
"";
20023 AddedString = OneFailureString;
20027 AddedString = TwoOrMoreFailureString;
20029 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
20030 AnsiString Rating =
"";
20031 if(OverallScorePercent == 100)
20033 Rating =
"Perfect!";
20035 else if(OverallScorePercent >= 95)
20037 Rating =
"Excellent";
20039 else if(OverallScorePercent >= 90)
20041 Rating =
"Very good";
20043 else if(OverallScorePercent >= 80)
20047 else if(OverallScorePercent >= 70)
20051 else if(OverallScorePercent >= 60)
20053 Rating =
"Unacceptable" + AddedString;
20055 else if(OverallScorePercent >= 50)
20057 Rating =
"Poor" + AddedString;
20059 else if(OverallScorePercent >= 40)
20061 Rating =
"Bad" + AddedString;
20063 else if(OverallScorePercent >= 30)
20065 Rating =
"Very bad" + AddedString;
20067 else if(OverallScorePercent >= 20)
20069 Rating =
"Terrible" + AddedString;
20071 else if(OverallScorePercent >= 10)
20073 Rating =
"Appalling" + AddedString;
20075 else if(OverallScorePercent >= 5)
20079 Rating =
"Disastrous - potential loss of life";
20084 Rating =
"Dire" + AddedString;
20087 else if(OverallScorePercent < 5)
20091 Rating =
"Catastrophic - loss of life";
20095 Rating =
"Abysmal";
20098 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
20102 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
20104 PerfFile <<
'\n' <<
"***************************************";
20114 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20164 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20199 int IncrementalMinutes = 0;
20213 bool TrainOperatingFlag =
false;
20218 TrainOperatingFlag =
true;
20222 if(TrainOperatingFlag)
20230 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
20277 AnsiString HeadCode;
20281 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20285 HCandTrainPosParam.first = HeadCode;
20286 HCandTrainPosParam.second = TrainID;
20288 if((TimeToAct >= 0) && (TimeToAct < 59.9))
20291 OpTimeToActMultiMapEntry.first = TimeToAct;
20292 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20321 float TimeToAct = 0;
20322 int DistanceToRedSignal = 0;
20325 ContinuationEntryVecPosVector.clear();
20326 bool LaterTrain =
false;
20330 LaterTrain =
false;
20331 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
20342 if(!ContinuationEntryVecPosVector.empty())
20344 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
20346 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
20360 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
20361 AnsiString HeadCode = CTEIt->second.HeadCode;
20362 float CurrentStopTime;
20363 float LaterStopTime;
20364 float RecoverableTime;
20367 int DistanceToExit;
20369 bool SigControlAndCanPassRedSignal =
false;
20377 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
20383 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
20384 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
20387 if(AvTrackSpeed < 30)
20391 if(DistanceToRedSignal == -1)
20397 int Speed = AvTrackSpeed;
20398 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
20399 if(AvTrackSpeed > MaxSpeed)
20403 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
20406 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
20409 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
20414 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
20415 TimeToAct += MinsBefEnter;
20418 HCandTrainPosParam.first = HeadCode;
20419 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
20422 if(TimeToAct < 59.9)
20424 OpTimeToActMultiMapEntry.first = TimeToAct;
20425 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
20450 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
20460 TimeToExitMultiMapEntry.first = ExitPair;
20461 TimeToExitMultiMapEntry.second = ExitInfo;
20471 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
20472 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
20481 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
20482 int DistanceToRedSignal = 0;
20483 DistanceToExit = -1;
20484 ExitPair.first = -1;
20485 ExitPair.second = -1;
20486 int CumTrackSpeed = 0;
20488 int TrackSpeedCount = 0;
20489 float KmPerLocationStop;
20490 float MaxAllowableSpeed;
20500 int CurrentElement = TrackVectorPosition;
20501 int CurrentEntryPos = TrackVectorPositionEntryPos;
20506 CurrentStopTime = 0;
20508 RecoverableTime = 0;
20509 if(CurrentElement == -1)
20514 int CurrentExitPos;
20519 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
20523 CurrentExitPos = 1;
20527 CurrentExitPos = 3;
20532 CurrentExitPos = 0;
20568 CurrentStopTime = float(TimeToDepart);
20574 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20585 else if(SigControlAndCanPassRedSignal)
20590 if((NextEntryPos == 0) || (NextEntryPos == 2))
20611 CurrentElement = NextElement;
20612 CurrentEntryPos = NextEntryPos;
20613 CurrentExitPos = NextExitPos;
20625 int LaterStopNumber = 0;
20629 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
20638 if(CurrentEntryPos > 1)
20653 DistanceToExit = DistanceToRedSignal;
20658 if(TrackSpeedCount > 0)
20660 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20664 if(CurrentEntryPos > 1)
20675 if(LaterStopNumber > 0)
20677 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20678 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20684 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20688 if(AvTrackSpeed > MaxAllowableSpeed)
20690 AvTrackSpeed = MaxAllowableSpeed;
20702 bool StopRequired =
false;
20719 int TrainOnElement;
20726 if(CurrentEntryPos > 1)
20735 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
20744 double StopTimeDouble;
20757 if(StopTimeDouble < 0.5)
20759 StopTimeDouble = 0.5;
20763 LaterStopTime += float(StopTimeDouble);
20764 RecoverableTime += StopTimeDouble - 0.5;
20765 if((LaterStopNumber == 1) && (TrainID > -1))
20773 if((AVPtr + 1)->FormatType ==
TimeLoc)
20777 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
20779 if(StopTimeDouble < 0.5)
20781 StopTimeDouble = 0.5;
20784 LaterStopTime += float(StopTimeDouble);
20785 RecoverableTime += StopTimeDouble - 0.5;
20786 if((LaterStopNumber == 1) && (TrainID > -1))
20802 if(NextElement == -1)
20811 if((NextEntryPos == 0) || (NextEntryPos == 2))
20832 CurrentElement = NextElement;
20833 CurrentEntryPos = NextEntryPos;
20834 CurrentExitPos = NextExitPos;
20838 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
20851 if(TrackSpeedCount > 0)
20853 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
20857 if(CurrentEntryPos > 1)
20868 if(LaterStopNumber > 0)
20870 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
20871 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
20877 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
20881 if(AvTrackSpeed > MaxAllowableSpeed)
20883 AvTrackSpeed = MaxAllowableSpeed;
20886 return(DistanceToRedSignal);